如何将 IEnumerable 方法转换为异步工作 [duplicate]

How can I convert IEnumerable method to work asynchronously [duplicate]

提问人:Amir M 提问时间:11/8/2023 最后编辑:ServyAmir M 更新时间:11/16/2023 访问量:77

问:

我正在使用 c#、.net 6.0

我正在尝试将 IEnumerable 方法和 ot 的调用方方法转换为异步工作。

我有一个看起来像这样的代码:

    public IEnumerable<MyUser> getUsers()
    {
        return AccountById
            .Keys
            .SelectMany(accountId => {
                try
                {
                    return getUsersFor(accountId)
                        .Select(x => new MyUser(x,
                            SetAccountUniqueName(AccountById[accountId].Name,
                                AccountById[accountId].Id)));
                }
                catch (Exception ex)
                {
                    _log.Error(ex);
                    return Enumerable.Empty<MyUser>();
                }
            });
    }

    public IEnumerable<User> getUsersFor(string accountId)
    {
        ListUsersResponse usersResponse;
        string marker = null;
        do
        {
            using (var myClient = new ServiceClient(pass))
            {
                usersResponse =
                    myClient.ListUsersAsync(
                            new ListUsersRequest { Marker = marker, MaxItems = MAX_ITEMS })
                        .Result;
                foreach (var user in usersResponse.Users)
                {
                    yield return user;
                }
            }

            marker = usersResponse.Marker;
        } while (usersResponse.IsTruncated);
    }

如何将 getUsers() 和 getUsersFor() 转换为异步方法?

C# LINQ async-await yield

评论

0赞 Denis Micheal 11/8/2023
在命名方法时遵循 c# 约定,方法名称应该在 PascalCase 中。
0赞 Servy 11/9/2023
一旦你的问题被回答,就把你的问题编辑成一个完全不同的问题,这是不合适的。如果您有新问题,请提出新问题。

答:

-1赞 Leonardo Herrera 11/8/2023 #1

除非我遗漏了什么,否则您只需要将您的签名从

 public IEnumerable<User> getUsersFor(string accountId)

 public async Task<IAsyncEnumerable<User>> getUsersFor(string accountId)

并删除对 in async 方法的调用并等待它们:.Result

usersResponse = await myClient
    .ListUsersAsync(new ListUsersRequest { Marker = marker, MaxItems = MAX_ITEMS });

评论

0赞 Amir M 11/8/2023
这给出了一个错误 - 'getUsersFor(string)' 的正文不能是迭代器块,因为 'Task<IEnumerable<User>>' 不是迭代器接口类型
2赞 phuzi 11/8/2023
请尝试public async IAsyncEnumerable<User> getUsersFor(string accountId)
-1赞 dropoutcoder 11/8/2023 #2

您需要删除方法并将其更改为与 and 关键字异步,并将返回类型更改为 和 。.ResultasyncawaitTask<IEnumerable<MyUser>>Task<IEnumerable<User>>

public async Task<IEnumerable<MyUser>> GetUsersAsync()
{
    var result = new List<MyUser>();

    foreach(var accountId in AccountById.Keys)
    {
        try
        {
            var user = await GetUsersForAsync(accountId);
            result.Add(new MyUser(user, SetAccountUniqueName(AccountById[accountId].Name,
                            AccountById[accountId].Id)));
        }
        catch (Exception ex)
        {
                _log.Error(ex);
                return Enumerable.Empty<MyUser>();
        }
    }
}

public async Task<IEnumerable<User>> GetUsersForAsync(string accountId)
{
    ListUsersResponse usersResponse;
    string marker = null;
    do
    {
        using (var myClient = new ServiceClient(pass))
        {
            usersResponse =
                await myClient.ListUsersAsync(
                        new ListUsersRequest { Marker = marker, MaxItems = MAX_ITEMS });

            foreach (var user in usersResponse.Users)
            {
                yield return user;
            }
        }

        marker = usersResponse.Marker;
    } while (usersResponse.IsTruncated);
}

评论

0赞 Amir M 11/8/2023
这给出了一个错误 - 'getUsersFor(string)' 的正文不能是迭代器块,因为 'Task<IEnumerable<User>>' 不是迭代器接口类型
0赞 dropoutcoder 11/9/2023
哦,对不起。我忘了更改返回类型。现在就试试吧。
0赞 Amir M 11/9/2023
我不确定您更改了什么,但我仍然收到相同的错误(以及来自“选择”的错误......
0赞 dropoutcoder 11/9/2023
另一个更新。foreach 而不是 LINQ。