【问题标题】:.NET C# async await. whenall does not wait for tasks.NET C# 异步等待。 whenall 不等待任务
【发布时间】:2014-06-24 15:23:45
【问题描述】:

我在 .NET Framework 4.5 中使用 await/async/whenall 处理多线程时遇到问题。

我通过循环调用调用了数千个线程。

List<Task<string>> t = new List<Task<string>>(); 
for (Row = 0; Row < lines.Count; Row++)
{        
    t.Add(AccessPaymentVault(Row, credentials, cts.Token));
}
string[] str_list = await Task.WhenAll(t.ToArray());

AccessPaymentVault 功能用于连接保险库网络服务和检索信用卡信息。

async Task<string> AccessPaymentVault(int row, Credentials credentials, CancellationToken ct){
    var data = await Task.Run(() =>
    {
      return Tokenization.Retrieve(credentials, lines[row][CCColumnToken]);
    }, ct);

    return Encryptor.Decrypt(data);
}

Tokenization.Retrieve 是最waited 函数,它连接到webservice。 WhenAll 似乎没有等待所有任务,因为结果中的某些记录随机丢失。 当我第一次运行时,它会检索所有记录。 在第二次运行中,中间的一些记录丢失了。 在第三次运行中,第二次运行中丢失的记录在那里,但其他记录丢失了。

我猜问题出在 WhenAll 但不确定。

非常感谢任何形式的帮助。

谢谢。

【问题讨论】:

  • 这听起来很像stackoverflow.com/q/23936521/120955Tokenization.Retrieve() 自己异步执行吗?
  • 不,它没有。这就是为什么我使用 Task.Factory.StartNew 来实现这个功能。
  • 当您说“中间有些记录丢失”时,您是什么意思?你用什么代码来查看有哪些记录?
  • 就使用 async/await 而言一切看起来都很好。只是几个想法:1. Tokenization.Retrieve 中有一个共享状态,它可能由于多线程而被破坏 2. 你可能会在 Tokenization.Retrieve 中吞下一些异常
  • Max,你解决了这个问题!由于与服务器的连接过多,引发了异常。在捕获部分,我尝试再次连接并解决了。写一个答案,我会接受你的答案。你救了我。非常感谢!

标签: .net multithreading asynchronous async-await


【解决方案1】:

现在建议的启动新任务的方法是 Task.Run 而不是 Task.Factory.StartNew,除非您需要对任务进行更高级别的控制。

在您的情况下,主要问题是结果类型将是任务,导致这里有一些嵌套。 但幸运的是,有一种方法 - Task.Unwrap。

因此,如果您调用 Task.Run - Task.Factory.StartNew 和 Task.Unwrap 会自动调用。

查看此链接: http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx

还有一篇好文章:StartNew is Dangerous

来自 cmets 的更新

就使用 async/await 而言,一切看起来都很好。 只是几个想法:

  1. Tokenization.Retrieve 中有一个共享状态,可能由于多线程而被破坏
  2. 您可能会在 Tokenization.Retrieve 中吞下一些异常

【讨论】:

  • 马克斯,感谢您的回答。我将 startNew 更改为 Task.Run 但它有同样的问题。我正在将问题编辑到 Task.Run 中,以免造成更多混乱。
猜你喜欢
  • 1970-01-01
  • 2014-09-06
  • 2014-03-18
  • 2016-07-07
  • 2016-03-25
  • 2017-10-09
  • 2013-02-10
相关资源
最近更新 更多