繁体   English   中英

无法在Parallel.Foreach内部使用await。 错误:-'await'运算符只能在异步lambda表达式中使用

[英]Can not use await inside a Parallel.Foreach . error :- The 'await' operator can only be used within an async lambda expression

我在asp.net mvc-5 Web应用程序中有以下方法:-

public async Task <List<Details>> Get()
{
    Parallel.ForEach(resourcesinfo.operation.Details,new ParallelOptions { MaxDegreeOfParallelism = 20 }, (c) =>
    {
        ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
        using (WebClient wc = new WebClient()) 
        {
            string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
            string tempurl = url.Trim();

            var json =  await wc.DownloadStringTaskAsync(tempurl);
            resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
        }
        //code goes here

但我收到此错误:-

“ await”运算符只能在异步lambda表达式中使用。 考虑使用'async'修饰符标记此lambda表达式

那么任何人都可以这样做吗?

Parallel.ForEeach不适用于异步函数,您需要使用更现代的类,例如TPL Dataflow中的类 您可以通过将NuGet软件包安装到项目Microsoft.Tpl.Dataflow来获取它。 您可以重新创建以前的代码为

private const int MAX_PARALLELISM = 20

public async Task <List<Details>> Get()
{
    var block = new ActionBlock<Entry>(async (c) => 
        {
            ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
            using (WebClient wc = new WebClient()) 
            {
                string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
                string tempurl = url.Trim();

                var json =  await wc.DownloadStringTaskAsync(tempurl);
                resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
            }
            //code goes here
        }
        ,new ExecutionDataflowBlockOptions 
                   { 
                         MaxDegreeOfParallelism = MAX_PARALLELISM
                   });

    foreach(var entry in resourcesinfo.operation.Details)
    {
        await block.SendAsync(entry);
    }

    block.Complete();
    await block.Completion;

    //More code here    
}

考虑了一下之后,这是一个稍微复杂一点的版本,它执行从读取记录到从Get()返回结果的整个管道。

private const int MAX_PARALLELISM = 20

public async Task<List<Details>> Get()
{
    List<Details> result = new List<Details>();

    var getRecordBlock = new TransformBlock<Entry, ResourceAccountListInfo>(async (c) =>
        {
            ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
            using (WebClient wc = new WebClient())
            {
                string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
                string tempurl = url.Trim();

                var json = await wc.DownloadStringTaskAsync(tempurl);
                resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
            }
            return resourceAccountListInfo;
        }
        , new ExecutionDataflowBlockOptions
        {
            MaxDegreeOfParallelism = MAX_PARALLELISM
        });

    //Defaults to MaxDegreeOfParallelism = 1
    var addToListBlock = new ActionBlock<ResourceAccountListInfo>(info =>
    {
        Details detail = TurnResourceAccountListInfoInToDetails(info);
        result.Add(detail);
    });

    getRecordBlock.LinkTo(addToListBlock, new DataflowLinkOptions { PropagateCompletion = true});

    foreach (var entry in resourcesinfo.operation.Details)
    {
        await getRecordBlock.SendAsync(entry);
    }

    getRecordBlock.Complete();
    await addToListBlock.Completion;

    return result;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM