parallel.for循环中的异步任务

San*_*anj 2 .net c# winforms task-parallel-library async-await

我有一个异步方法从Parallel.For下面的代码调用.现在看代码它是非常直接的,除了JsonParse类有一个静态方法,它只是调用Web服务来下载json字符串并将其转换为PairResults对象并返回.

我遇到的问题是Parallel.For循环从不退出,我可以清楚地看到数据来自网络摄像头"item.part1 = data.value"一切正常,但updateAllResults永远不会完成.我究竟做错了什么?

public void updateAllResults()
{ 
    Parallel.For(0, PairList.Count(), (i) =>
    {            
         var item = PairList[i];
         var data = (Parse.JsonParse<PairResults>
                             .getJsonString("http://localhost:22354/" 
                                                        + item.Original)).Result;
         item.part1 = data.value;
    }); 
}
Run Code Online (Sandbox Code Playgroud)

nos*_*tio 5

这是一个反模式Parallel.For,因为你只是用它来启动异步操作并阻止它们.这样,它将阻止有限数量的池线程,并且实际的并行度可能比使用任务时要低得多:

public void updateAllResults()
{
    var tasks = PairList.Select(async (item) => 
    {
        var data = await Parse.JsonParse<PairResults>
            .getJsonString("http://localhost:22354/" + item.Original).
            .ConfigureAwait(false);

        item.part1 = data.value;
    });

    Task.WaitAll(tasks.ToArray());
}
Run Code Online (Sandbox Code Playgroud)

此外,您的问题标记为标记.无论Parallel.For与上面的代码会阻塞你的UI线程,如果你在一个WinForms应用程序中使用它.正确的解决方案是使用Task.WhenAll:

public async Task updateAllResults()
{
    var tasks = PairList.Select(async (item) => 
    {
        var data = await Parse.JsonParse<PairResults>
            .getJsonString("http://localhost:22354/" + item.Original)
            .ConfigureAwait(false);

        item.part1 = data.value;
    });

    await Task.WhenAll(tasks.ToArray());
}

// button click handler
async void button_Click(object s, EventArgs e)
{
    this.button.Enabled = false;
    try
    {
        await updateAllResults()
    }
    finally
    {
        this.button.Enabled = true;
    }
}
Run Code Online (Sandbox Code Playgroud)