【问题标题】:Task reports IsCompleted but still blocks on Result?任务报告 IsCompleted 但仍阻止 Result?
【发布时间】:2012-02-16 09:57:52
【问题描述】:

我在使用 .Net 4 类 System.Threading.Tasks 时遇到了一些奇怪的行为。这个例子最好地证明了这一点:

var t = FunctionThatReturnsTaskAsync();
Trace.TraceInformation("Completed: " + t.IsCompleted);
return t.Result;

输出:“Completed: true”,但代码(几千次运行一次)然后永远阻塞在 t.Result。它既不返回也不抛出异常。这怎么可能!

返回的任务完成起来要快一些,所以它可以在第二行完成也就不足为奇了。奥秘在于为什么 t.Result 会阻塞。

【问题讨论】:

  • 该功能是如何实现的?
  • 奇怪。您能否发布一个展示该问题的最小示例?
  • @CodeInChaos,最小的例子就可以了,但由于这种情况发生在“几千次运行中”,我不确定它是否可能。
  • @svick 这样的示例会在循环中调用此代码一百万次,因此很可能会出现问题。
  • Task 类没有 Result 属性。 Start() 方法调用是完全不可见的。发布可以实际重现问题的代码。

标签: c# .net concurrency


【解决方案1】:

异步方法本身返回Tasks,你可能有一个Task>,内部任务由于'async'在'finishing'之前返回,而外部Task认为已经完成。

请参阅 Stephen Toub 的博客文章:

http://blogs.msdn.com/b/pfxteam/archive/2012/02/08/10265476.aspx

http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx

请允许我摘录一段相关的引述:

要理解这种效果,我们需要记住异步方法是如何运作的。当您调用异步方法时,它开始同步运行。如果方法中没有任何等待,或者方法中的所有等待都在等待时已经完成的等待对象上,那么该方法将完全同步运行。但是,当该方法遇到第一个产生的等待时,异步方法返回。对于返回 Task 或 Task 的 async 方法,此时该方法返回代表 async 方法执行的 Task 或 Task,调用者可以使用该任务同步等待(例如 Wait())或异步等待(例如,await、ContinueWith)使方法异步完成。但是,在 void 方法的情况下,不会返回任何句柄。因此,异步 void 方法通常被称为“一劳永逸”。

【讨论】:

  • 这个问题专门询问.ENET 4.0,你解释.NET 5?!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2019-10-09
  • 2017-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多