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

泄露秘密 提交于 2019-12-12 00:44:03

问题


I have the following method inside my asp.net mvc-5 web application :-

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

but I am getting this error :-

The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier

so can anyone adivce on this please ?


回答1:


Parallel.ForEeach is not designed to work with asynchronous functions, you need to use more modern classes like the ones in TPL Dataflow. You get it by installing the NuGet package to your project Microsoft.Tpl.Dataflow. You could recreate your previous code as

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    
}

After thinking for a bit, here is a slightly more complicated version that does the entire pipeline from reading the records in to returning a result from 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;
}


来源:https://stackoverflow.com/questions/38077791/can-not-use-await-inside-a-parallel-foreach-error-the-await-operator-can

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!