gpt4 book ai didi

c# - 为什么在 UI 线程上调用 Thread.Join() 不会挂起我的应用程序?

转载 作者:太空狗 更新时间:2023-10-29 20:52:41 25 4
gpt4 key购买 nike

根据我的理解(我不擅长线程),Join() 会阻塞调用线程,直到调用 Join() 的线程返回。

如果是这样并且 Join() 是从 UI 线程调用的,那么为一些长时间运行的操作创建新线程就没有任何意义。 SO 上有一些问题问为什么 Join() 会挂起应用程序。这对我来说看起来很自然。

顺便说一句,即使它看起来很自然,我的应用程序也不会相应地运行。它不会挂起我的应用程序。

没有线程的代码会挂起应用程序:-

string retValue = "";
retValue = LongRunningHeavyFunction();
txtResult.Text = retValue;

带有不会挂起应用程序的线程的代码:-

string retValue = "";
Thread thread = new Thread(
() =>
{
retValue = LongRunningHeavyFunction();
});
thread.Start();
thread.Join();
txtResult.Text = retValue;

以上代码在没有挂起应用程序的情况下运行良好。函数调用大约需要 15-20 秒。为什么应用程序没有挂起?

这对我来说不是问题;实际上这是一个好消息。但我只是不明白它有什么区别?这与我阅读和学习的内容不符。

如果重要的话,我正在使用 DotNet Framework 4.0。

最佳答案

由于 Main() 入口点上的 [STAThread] 属性,程序的 UI 线程创建了一个 STA,一个单线程单元。另请查看 Thread.SetApartmentState()。 STA 对非线程安全的代码非常友好,通常是您看不到的代码,因为它是另一个程序的一部分。

就像涉及将数据放在剪贴板上的代码,在拖放操作中提供数据,显示 OpenFiledialog 时激活的 shell 扩展,像 WebBrowser 这样的控件需要客户端代码有一个调度程序,所以它可以引发 DocumentCompleted 事件、监听通知的 Windows Hook 、依赖可访问性 API 实现 UI 自动化或屏幕阅读器的代码。等等。

这些代码都不需要是线程安全的,即使涉及不同进程中的多个线程也是如此。编写线程安全的代码通常是困难的,它变得非常困难,因为作者没有任何好的方法来测试它。他不可能针对每一个可能激活他的代码的程序来测试它。公寓的发明就是为了解决这个问题,从而消除了编写线程安全代码的需要。

STA 是您做出的 promise 。你发誓,发誓,你的 UI 线程表现良好,它必须有一个调度程序(又名泵消息循环)并且绝不能阻塞。调度程序必须以线程安全的方式运行代码,它是 producer-consumer problem 的通用解决方案。 .而且您绝不能阻塞,因为这样做很可能会导致其他程序员的代码出现死锁。您永远无法调试的那种死锁,因为您没有该代码的源代码。 Winforms、WPF 或现代 UI 程序的 UI 线程始终实现这一 promise ,这是 UI 线程与您可能使用的任何其他线程不同的基本原因。

足够多的介绍,Thread.Join() 调用阻塞并因此违反了 STA 契约。这非常糟糕,所以 CLR 设计师 did something about it .他们通过阻塞的方式实现了 Join(),以防止在 STA 线程上调用它,正如您所发现的。

他们通过实现 Application.DoEvents() 的风格来做到这一点.这是一种非常臭名昭著的避免 UI 线程变得无响应的方法。它会导致很难诊断重入错误。他们的版本并不像 DoEvents() 那样糟糕,它非常有选择性地允许分派(dispatch)什么样的消息以将风险降至最低。

这通常没问题,但是永远您不想有意测试自己。重入错误是非常棘手的错误,与线程竞争错误一样糟糕。因此,永远不要在 UI 线程上使用 Thread.Join()。 .NET Framework 为 BackgroundWorker 和 Task 类提供了极好的替代方案,它们都为您提供了在线程完成时执行代码(无论 Join() 调用之后)的非常好的方法。

关于c# - 为什么在 UI 线程上调用 Thread.Join() 不会挂起我的应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38911758/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com