parallel.for循环中的异步任务

时间:2014-03-14 11:33:40

标签: c# .net 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;
    }); 
}

2 个答案:

答案 0 :(得分: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());
}

此外,您的问题标有标记。如果您在WinForms应用程序中使用它,Parallel.For和上面的代码都将阻止您的UI线程。正确的解决方案是使用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;
    }
}

答案 1 :(得分:2)

Parallel.For块直到所有迭代都已执行或者循环中断​​,就像常规for语句一样。确保已下载所有数据。之后Parallel.For应该完成,因此也就是方法。