【问题标题】:Async task inside parallel.for loopparallel.for 循环中的异步任务
【发布时间】:2014-04-19 16:14:33
【问题描述】:

我使用下面的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;
    }); 
}

【问题讨论】:

  • 应该会完成,但可能需要很长时间,具体取决于 PairList 中的项目数。话虽如此,请考虑通过使用 async (i) =&gt;await 而不使用 .Result 调用来实现真正的异步。
  • 啊,这就像魔术一样。将方法更改为 async (i) => 就是答案。

标签: c# .net winforms task-parallel-library async-await


【解决方案1】:

这是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;
    }
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2017-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2014-07-24
      • 1970-01-01
      • 2023-03-12
      相关资源
      最近更新 更多