And*_*ers 8 c# multithreading manualresetevent cancellation cancellation-token
我正在编写一个包含几个线程的程序,每个程序都有一个while循环,直到用户指定它应该停止.我想到了退出循环的几种方法,以及随后的线程,并在下面概述了这些方法.
问题
以下是方法.
该bool方法
最初,我已经声明了一个bool并且刚刚声明循环运行直到用户将bool设置为false : while(running) { Thread.Sleep(10); /*do work*/ }. 然后我思索是否完全是线程安全的.如果编译器进行了一些优化并将bool移动到寄存器,该怎么办?在这种情况下,线程会看到bool的不同值.因此,我使用volatile关键字标记bool 以避免编译器优化.
该ManualResetEvent方法
我的下一个方法是创建一个ManualResetEvent,并且只是说,当WaitOne()为false时bool运行:while(!mre.WaitOne(10)) {/*do work*/}.这将阻塞10ms,然后一遍又一遍地运行循环,直到我们这样做mre.Set()并且循环退出.
该CancellationToken方法
我还没有尝试过这种方法,但是我读了几个人们喜欢用这种方式取消线程的地方.它显然是线程安全的.可以定义一个CancellationTokenSource,调用它cts,然后传递cts.Token给新线程运行的方法,并使用if语句检查是否已请求取消:while(!token.IsCancellationRequested) { Thread.Sleep(10); /*do work*/ }
更新1:
我发现了一篇类似的帖子,得出的结论是该MRE方法明显慢于该CancellationToken方法.有关完整信息,请参阅此处:停止线程,ManualResetEvent,volatile boolean或cancellationToken
更新2:
当谈到将这种bool方法与其他两种方法进行比较时,Eric Lippert在这里有一个很好的答案:AutoResetEvent vs. boolean来阻止一个线程
更新3:
我找到了另一条相关的信息.取消取消后,取消权限无法重置.因此,当您只想暂时取消循环,以后再次启动它时,它并不理想.为此,MRE可能会更好(因为您可以根据自己的内容设置和重置).
大多数情况下,您的线程不会在紧密循环中运行,从而消耗所有 CPU 周期,通常您正在等待某种事件,当您等待时,您不能真正等待 bool。您的事件可以超时,等待超时,检查布尔值,然后返回等待。这会产生令人讨厌的代码,也意味着你的线程不会退出,直到超时发生,或者你让你的CPU检查一个布尔值。
Reset Event 没问题,你当然可以使用它,但是 CancelellationToken 工作得很好,并且正是为此而设计的。
| 归档时间: |
|
| 查看次数: |
2675 次 |
| 最近记录: |