因此,在对多线程以及如何处理线程完成进行了大量研究之后,我遇到了几个解决方案。有些解决方案似乎比其他解决方案更有用,更有用。我想花一些时间来解释我已经知道的东西,然后作为回报,我想更好地理解为什么这些解决方案的实施方式如此不同。这篇文章的原始主题是发现Thread.Sleep(x)
和do {} while (b);
之间的区别。根据我的理解,这两种解决方案只是在Thread.Sleep(x)
将使用比后者更少的CPU的意义上是不同的。旋转等待(空循环)将基本上从CPU的尖峰百分比高达85%连续运行,这对于最快的计算机来说是一件坏事,我只能想象这会对普通家用电脑做些什么。
Thread.sleep代码
MSDN明确指出,在使用Thread.Sleep(x)
时,线程在指定的时间内不会执行。
操作系统不会安排线程执行指定的时间。
Thread.Sleep(x)
的备注部分建议使用其他选项,例如使用Timeout.Infinite
或Mutex
,Monitor
,Semaphore
等来同步线程和以更好的方式管理资源。你对这个有什么看法?这不会像用旋转等待冻结GUI一样糟糕吗?
MSDN还指出,由于系统时钟以称为时钟分辨率的特定速率滴答,实际时序可能不是指定的确切值,因为它被调整为与时钟滴答一致。
旋转等待
根据我的理解,这是一个完全不好的做法。一旦启动一个空循环,它实际上会阻塞它正在执行它的线程。这可能导致冻结,崩溃和无响应的GUI,更不用说这会使用户的计算机显着降低,因为编译器和操作系统都不了解可以优化循环以节省性能上的不必要的命中。从我的阅读来看,普通计算机可以有一到两个核心的CPU运行在100%,这仅仅是因为连续执行空循环。我读过的旋转等待的唯一有效用法是线程同步。你用它来同步线程吗?我认为有更好的解决方案,并且使用空循环也会对调试产生问题。
后台工作人员
BackgroundWorker
对象有一个名为RunWorkerCompleted
的事件,在DoWork
事件处理程序返回时引发。根据我的线程经验(这是最小的),我总是使用此事件在线程操作完成后执行代码。这个事件要考虑的最重要的事情是,如果后台线程被取消,那么你没有真正的知道方式,因为如果CancellationPending标志被设置为true,Canceled
标志将不会被设置为true。错过了投票循环。 MSDN更彻底地说明了这一点:
请注意,DoWork事件处理程序中的代码可能会在取消请求时完成其工作,并且您的轮询循环可能会错过CancellationPending设置为true。在这种情况下,即使发出了取消请求,RunWorkerCompleted事件处理程序中System.ComponentModel.RunWorkerCompletedEventArgs的Canceled标志也不会设置为true。这种情况称为竞争条件,是多线程编程中的常见问题。有关多线程设计问题的更多信息,请参阅托管线程最佳实践。
最后的想法
由于有很多方法可以同时完成多个任务,这通常被认为是最佳实践,为什么它是最佳实践,它们之间最大的区别是什么?我已经对此深思熟虑,对于有更多经验的开发人员的建议非常好奇。
注意
我已经深入研究Google,MSDN,StackOverflow和Daniweb,为这个问题做了很好的研究工作。最后的想法区域是我想要回答的主要问题集。我相信这里的原帖太广泛了,需要进一步的信息和清晰度才能收到我真正想要的答案,我很抱歉花了这么长时间来澄清我的问题。
感谢大家的投入!
-Jamie
重复差异
在this post标记为与此重复的{{3}}中,OP正在请求有关如何解决其BackgroundWorker
对象未实际提升RunWorkerCompleted
事件的问题的信息,我没有这个问题,我的帖子也没有要求提供有关此问题的信息。我的帖子要求详细说明在执行最终操作之前等待线程完成的三种最常见方法之间的区别。我主要关注的是每个解决方案的优势和劣势,以及任何被认为是多线程常见或最佳实践的解决方案。