【问题标题】:Strange behavior of Parallel.ForEachParallel.ForEach 的奇怪行为
【发布时间】:2014-06-29 21:08:19
【问题描述】:

我有以下代码:

Parallel.ForEach(xRoot.Elements("key"), xKey =>
{
    int id = int.Parse(xKey.Attribute("id").Value);
    string code = xKey.Attribute("code").Value;

    AccountStatus accountStatus = SomeClient.GetAccountStatusAsync(id, code).Result;
);

xRoot.Elements("key") 的计数是 3,但 ForEach 只迭代了 2 次。为什么?

【问题讨论】:

  • 您确定没有引发异常吗?您是否在 ForEach 函数的开头设置了断点并验证它已运行 3 次? xRoot.Elements("key") 的确切类型是什么?
  • 使用await,而不是.Result。 (和Task.WhenAll(elements.Select()),而不是Parallel.ForEach()
  • 为了确保它只执行两次,将此声明放在循环之前int loopCounter = 0; 并在循环内添加Interlocked.Increment(ref loopCounter);。处理完成后检查该值以查看它执行了多少次。

标签: c# .net async-await windows-8.1 parallel.foreach


【解决方案1】:

混合Parallel.ForEachasync/await isn't a good idea。您不需要异步方法在并行中执行,您需要它们同时执行。您当前的代码使用线程池线程来阻塞 I/O 操作,缺少异步 api 的优势。

试试这个:

var codeIds = xRoot.Elements("key").Select(xKey => new { Id = int.Parse(xKey.Attribute("id").Value, Code = xKey.Attribute("code").Value  });

var codeTasks = codeIds.Select(x => SomeClient.GetAccountStatusAsync(x.Id, x.Code));

await Task.WhenAll(codeTasks);

【讨论】:

  • 太棒了。如果我需要添加嵌套循环怎么办?例如,var codeTasks = codeIds.Select(x => SomeClient.GetAccountStatusAsync(x.Id, x.Code).ContinueWith(blabla)); Is it correct?
  • 可以这样做,但是你将等待从ContinueWith返回的任务,而不是从GetAccountStatusAsync返回的任务
【解决方案2】:

试试:

Parallel.ForEach(xRoot.Elements("key"), async xKey =>
{
   int id = int.Parse(xKey.Attribute("id").Value);
   string code = xKey.Attribute("code").Value;

   AccountStatus accountStatus = await SomeClient.GetAccountStatusAsync(id, code);
);

或者:

Parallel.ForEach(xRoot.Elements("key"), xKey =>
{
   try
   {
      int id = int.Parse(xKey.Attribute("id").Value); // maybe null reference here?
      string code = xKey.Attribute("code").Value; // or here?

      AccountStatus accountStatus = SomeClient.GetAccountStatusAsync(id, code).Result; // or even here?
   }
   catch (Exception ex)
   {
      throw; // add here a breakpoint and check what's up by checking 'ex' object
   }
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 2015-07-20
    • 2010-10-03
    • 2021-07-12
    相关资源
    最近更新 更多