我们有一项服务可以执行以下基本工作流程:
1) 启动、读取配置设置并在一个大循环中执行一些计算。
2)循环的每次迭代,它都需要能够检查服务是否被告知停止。它执行数据库提取、计算然后存储结果。我对代码在 SQL 事务中的执行情况没有信心,所以在这个阶段,很高兴假设我们只在每次迭代开始时检查服务停止。
3) 执行完所有迭代后,服务“休眠”一段时间。可能是5分钟。可能是12小时。它需要能够在这个睡眠期间“停止”!
目前,这是通过以下方式执行的:
private int threadSleepMinutes = 60;
private readonly Mutex mutTerminateService = new Mutex(false);
private Thread serviceThread;
private Thread serviceStopThread;
// Use this flag to allow the Start op to wait for serviceStopThread
// to get going before continuing to create the main loop thread
private volatile bool stopService = true;
public void Start()
{
this.serviceStopThread = new Thread(this.RunServiceStopThread);
this.serviceStopThread.IsBackground = true;
this.serviceStopThread.Start();
while (stopService)
{
Thread.Sleep(100);
}
// Some things renamed to anonymise... you get the idea!
this.serviceThread = new Thread(this.BigLoopMethod);
this.serviceThread.IsBackground = true;
this.serviceThread.Start();
}
public void Stop()
{
// Release the mutex to terminate the service
serviceStopThread.Resume();
// Wait 5s max
int timeout = 5000;
while (this.serviceThread.IsAlive && timeout > 0)
{
Thread.Sleep(100);
timeout -= 100;
}
}
private void RunServiceStopThread()
{
// To guarantee the same thread takes the mutex
// and releases it in dot net 4, do both ops in this single thread!
// Dot net 4 the Start() and Stop() are now usually on different threads.
mutTerminateService.WaitOne();
stopService = false;
// Suspend ourself
serviceStopThread.Suspend();
// Release the mutex
mutTerminateService.ReleaseMutex();
}
public void BigLoopMethod()
{
try
{
do
{
bool moreOperationsToGo = true; // Just dummy flags and 'stuff' methods here
while (moreOperationsToGo && !mutTerminateService.WaitOne(0))
{
DoStuff();
}
// Using this mutex here to sleep nicely - event driven.
// Gracefully continues after timeout and gracefully exits if
// triggered by the mutex.
}
while (!mutTerminateService.WaitOne(this.threadSleepMinutes * 60000));
}
catch (Exception ex)
{
// Exception handling & logging here
}
}
现在我收到消息说 Suspend 和 Resume 已弃用。在我的情况下,我确切地知道暂停是在什么代码上运行的,因为调用本身就是暂停它的原因!恢复,我确切地知道它会做什么。这样做的唯一原因是互斥锁在 dot net 3.5 中的 Start() 和 Stop() 中运行良好,但 dot net 4.0 发生了变化,因此 Start() 和 Stop() 位于不同的线程中并且它们标记了解决方法已过时!
有没有一种不错的、过时的方法来做到这一点?
谢谢