为什么在具有STAThreadAttribute的线程上不支持WaitAll方法?

时间:2017-11-22 08:44:55

标签: c# .net multithreading

This msdn article州:

  

具有STAThreadAttribute的线程不支持WaitAll方法。

如果有人搜索或搜索stackoverflow,他们会找到许多解决方法。

我想知道原因这是不受支持的。当然,这不是任意的,并且有充分的理由可能出现这种情况。什么是关于STA线程阻止或使WaitAll更难以完成其工作?

你能解释一下吗?

1 个答案:

答案 0 :(得分:3)

[STAThread]属性是一个承诺,穿越你的心希望死去。它告诉操作系统你创建了一个线程,这个线程是一个非线程安全的代码。你做的承诺是线程有一个调度程序循环(也就是消息循环),永远不会阻塞。调度程序循环解决producer-consumer problem,这是确保即使从工作线程进行原始调用也可以进行线程安全调用所必需的。永不阻塞的要求确保在必要时可以编组这些调用,并且不可诊断的死锁的风险很低。

换句话说,不仅WaitAll()是非法的,即使使用WaitOne()正式 verboten

避免使用WaitOne()并不是很困难,但还有其他一些常见且很难避免的阻塞方案。 Thread.Join()就是一个例子。因此,CLR设计师不是直接禁止所有这些,而是​​提出了支持这种有限阻塞的解决方案。 CLR中有一个调度程序循环,它接管你用Application.Run()开始的循环的角色。它大致类似于Application.DoEvents(),但不完全as dangerous通过过滤那种通常会导致重入错误的消息。

这是否是一个好的设计决定是相当有争议的btw。一般的问题是程序员偶然依赖它并且当他们发现这些等待实际上没有阻塞时会出现非常粗暴的意外。调试重入错误是一种非常小的乐趣,并且修复错误总是需要进行非平凡的重写。 CLR设计人员只是这样做,以便更容易移植代码,而不是提供功能。值得注意的是,这段代码从未发布过,不是在SSCLI中,而是在CoreCLR中,他们不希望任何人故意利用它。

尽管博客文章中有断言,但他们可以很容易地使WaitAll()以这种方式工作。但是他们把脚放在那个脚上,这太有帮助了。

过多的帮助原样。在可能考虑使用WaitOne()的地方,始终将代码后面的代码移动到BackgroundWorker.RunWorkerCompleted事件处理程序或从TaskScheduler.FromCurrentSynchronizationContext()获取的任务继续或在异步方法中等待之后。