为什么在UI线程上调用Thread.Join()时我的应用程序没有挂起?根据我的理解(我不擅长线程),Join()会阻塞调用线程,直到调用Join()的线程返回。如果这是真的并且Join()是从UI线程调用的,那么为某些长时间运行的操作创建新线程就没有意义。一些问题,那些询问为什么Join()挂起应用程序的人。看起来很自然。顺便说一下,尽管它看起来很自然,但我的应用程序并没有相应地运行。它不会挂起我的应用程序。没有挂起应用程序的线程代码:–stringretValue="";retValue=LongRunningHeavyFunction();txtResult.Text=retValue;应用程序未挂起的线程代码:-stringretValue="";线程thread=newThread(()=>{retValue=LongRunningHeavyFunction();});线程。开始();线程.加入();txtResult.Text=retValue;上面的代码很好,没有挂起应用程序函数调用大约需要15-20秒。为什么应用程序没有挂起?这对我来说不是问题;这实际上是个好消息。但我只是不明白它是如何产生影响的?它与我阅读和学习的内容不符。如果重要的话,我正在使用DotNetFramework4.0。由于Main()入口点上的[STAThread]属性,程序的UI线程创建了一个STA,一个单线程单元。另请查看Thread.SetApartmentState()。STA对非线程安全的代码非常友好,通常是您看不到的代码,因为它是另一个程序的一部分。就像将数据放在剪贴板上的代码,在拖放操作中提供数据,显示OpenFiledialog时激活的shell扩展,像WebBrowser这样的控件需要客户端代码来拥有一个调度程序,以便它可以引发DocumentCompleted事件,Windows监听通知、代码或屏幕阅读器的钩子,这些钩子依赖于UI自动化的可访问性API。等等,即使涉及到不同进程的多个线程,也不要求代码是线程安全的。一般来说,编写线程安全的代码是困难的,因为作者没有任何好的方法来测试它,所以变得非常困难。他无法测试每一个可能激活他的代码的程序。发明公寓是为了解决这个问题,而无需编写线程安全代码。STA是您的承诺。你发誓,发誓-希望死的风格,你的UI线程表现良好,它必须有一个不能阻塞的调度程序(又名泵消息循环)。调度程序以线程安全的方式运行代码是必需的,它是生产者-消费者问题的通用解决方案。而且你绝不能阻塞,因为这样做很可能会使其他程序员的代码陷入僵局。由于没有该代码的源代码而无法调试的死锁类型。Winforms、WPF或现代UI程序的UI线程始终履行这一承诺,这是UI线程不同于您可能使用的任何其他线程的根本原因。足够的介绍,Thread.Join()调用块,从而违反了STA合同。这非常糟糕,因此CLR设计者对此采取了一些措施。正如您所发现的,它们通过不阻塞来实现Join(),因为它是在STA线程上调用的。他们通过实现Application.DoEvents()的风格来做到这一点。这是避免UI线程变得无响应的一种非常臭名昭著的方法。它可能导致难以诊断重入错误。他们的版本并不像DoEvents()那样糟糕,DoEvents()非常有选择性地允许分派什么样的消息以将风险降至最低。这通常很好,但您永远不想故意测试自己。重入错误是非常严重的错误,与线程竞争错误一样严重。因此,永远不要在UI线程上使用Thread.Join()。.NETFramework为BackgroundWorker和Task类提供了很好的替代方案,它们为您提供了一种在线程完成时(在Join()调用之后)执行代码的非常好的方式。以上是C#学习教程:WhydoesThread.Join()nothangmyapplicationwhencalledontheUIthread?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
