簡體   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