c# – 停止线程,ManualResetEvent,volatile boolean或cancellationToken
作者:互联网
我在Windows服务中有一个Thread(STAThread),它执行大量工作.重新启动Windows服务时,我想优雅地停止此线程.
我知道几种方法
>一个不稳定的布尔值
> ManualResetEvent
> CancellationToken
据我所知,Thread.Abort是不行的……
什么是最佳做法?
该工作在另一个类中执行,而不是启动线程的类,因此有必要在构造函数中引入cancellationToken参数或者例如具有volatile变量.但我无法弄清楚什么是最聪明的.
更新
为了澄清一点,我已经结束了一个我正在谈论的非常简单的例子.如前所述,这是在Windows服务中完成的.现在我正在考虑在循环中检查的volatile布尔值或者cancelToken ….
我不能等待循环完成,如下所述,它可能需要几分钟,使得服务器的系统管理员认为当他们需要重新启动它时服务出现问题….我可以毫无问题地放弃所有循环中的工作没有问题,但是我不能用Thread.Abort来做它“邪恶”而且还调用了COM接口,因此需要进行小的清理.
Class Scheduler{
private Thread apartmentThread;
private Worker worker;
void Scheduling(){
worker = new Worker();
apartmentThread = new Thread(Run);
apartmentThread.SetApartmentState(ApartmentState.STA);
apartmentThread.Start();
}
private void Run() {
while (!token.IsCancellationRequested) {
Thread.Sleep(pollInterval * MillisecondsToSeconds);
if (!token.IsCancellationRequested) {
worker.DoWork();
}
}
}
}
Class Worker{
//This will take several minutes....
public void DoWork(){
for(int i = 0; i < 50000; i++){
//Do some work including communication with a COM interface
//Communication with COM interface doesn't take long
}
}
}
UPDATE
刚刚检查了性能,使用了在代码中“检查”isCancelled状态的cancellationToken,比在ManualResetEventSlim上使用waitOne要快得多.一些快速的图形,一个if在cancelToken迭代100.000.000次在for循环花费我约. 500毫秒,其中WaitOne的成本约为3秒.因此,在这种情况下,使用cancellationToken会更快.
解决方法:
您尚未发布足够的实施内容,但如果您可以使用,我强烈建议您使用CancellationToken.从可维护性的角度来看,使用和理解它非常简单.如果您决定拥有多个工作线程,也可以设置合作取消.
如果您发现自己处于此线程可能长时间阻塞的情况,最好设置您的体系结构,以便不会发生这种情况.当你告诉他们停止时,你不应该开始那些不会很好玩的线程.如果他们在你问他们时没有停止,那么唯一真正的方法是拆除这个过程并让操作系统杀死他们.
Eric Lippert在一个有点相关的问题here上发布了一个很棒的答案.
标签:c,multithreading,cancellation,cancellation-token 来源: https://codeday.me/bug/20190715/1469082.html