.NET线程模型以及Application.DoEvents和Thread.Sleep的区别

7
我们有一个桌面应用程序,在后台线程中执行一组相当严格的计算。其中一部分计算是在我们通过互操作访问的非托管库中执行的。我们发现,当我们启动计算时,UI线程在计算持续时间内变得不响应。我们原本认为框架会处理线程切换以允许UI保持响应,但事实并非如此。我们发现可以插入Thread.Sleep(0)或Application.DoEvents()来使UI响应。这会导致计算速度变慢。此外,非托管代码执行的计算部分可能需要30秒才能完成,在此期间应用程序始终无响应。整个计算可能需要2到5分钟才能完成。
这引出了以下问题:
- .NET框架关于UI和互操作的线程模型是什么? - 我们是否错误地认为框架应该处理后台和UI线程之间的线程切换? - 在这种情况下使用Thread.Sleep和Application.DoEvents有什么区别,哪个更好?

注意:这是非常旧的问答内容,请搜索更新的讨论以获取有关今天可用解决方案的良好答案。 - ToolmakerSteve
3个回答

3
你可以降低后台线程的优先级,这样操作系统会更频繁地抢占它。如果你拥有一些领域知识,想要控制何时进行抢占,可以使用Thread.Sleep(0),这会在有其他等待线程时放弃时间片。
Application.DoEvents会推送Windows消息队列,从而使你的应用程序响应按键或窗口调整等事件。Thread.Sleep会导致你的线程被抢占(或者在Thread.Sleep(0)的情况下不一定)。
同时阅读C#中的线程化

DoEvents是WinForms方法。VB(6和.NET)的运行时性能比C#慢。对于VB,在GUI线程上使用DoEvents,在后台线程上使用Sleep(0)。而在C#中,您根本不需要使用DoEvents,因为现在可以使用异步框架以及线程。此外,仅在必要时附加用户控件事件 - 即在通过代码调用事件处理程序时将其关闭,以避免事件集群炸弹和性能问题。 - Deano

2
您最好的选择是创建自己的“Thread”。使用“DoEvents”和“Thread.Sleep(0)”会阻塞计算,使其变慢。您可以将DLL调用包装在“ThreadStart”委托或“ParameterizedThreadStart”委托中,并在实例化“Thread”时使用委托名称作为参数。从那里开始,您只需要调用“Thread”的“Start”方法即可。

0

正确的做法是使用回调函数。请参阅Silverlight模型,学习如何使用异步方法(例如检索Web服务数据)。我知道这个问题已经“被解答”,但在我看来,答案并不理想。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接