/// <summary>
/// 长时间工作线程服务
/// </summary>
public class LongRunningThreadService
{
private CancellationTokenSource _stopCts;
private readonly ManualResetEvent _pauseEvent = new(false);
private Thread _workerThread;
public void Start()
{
_stopCts = new();
_pauseEvent.Set();
var thread = _workerThread ??= new Thread(ThreadJob) { IsBackground = true };
thread.Start(_stopCts.Token);
Console.WriteLine("Starting Service...");
}
public void Pause()
{
Console.WriteLine("Pausing Service...");
_pauseEvent.Reset();
}
public void Resume()
{
Console.WriteLine("Resuming Service...");
_pauseEvent.Set();
}
public void Stop()
{
Console.WriteLine("Stopping Service...");
_stopCts.Cancel();
_stopCts.Dispose();
_stopCts = null;
_workerThread = null;
}
/// <summary>
/// 线程委托:轮询工作
/// </summary>
/// <param name="obj"></param>
private void ThreadJob(object obj)
{
var token = (CancellationToken)obj;
while (!token.IsCancellationRequested)
{
_pauseEvent.WaitOne();
Console.WriteLine("Working...");
Process();
Thread.Sleep(1);
}
Console.WriteLine("Service Stopped");
}
/// <summary>
/// 模拟单个耗时任务
/// </summary>
private void Process()
{
Thread.Sleep(300);
}
}
- 关键点解释
- 使用CancellationTokenSource来控制工作线程的停止,将_stopCts作为线程委托启动参数传递(_stopCts调用Cancel方法时,委托方法的while轮询将会跳出,从而达到终止线程任务效果)。
- 使用ManualResetEvent信号量来控制工作线程的暂停、继续。该信号量调用Set方法时,将事件状态设置为“已触发”,所有等待该事件的线程(线程中调用该信号量WaitOne方法的地方)都会被唤醒,达到线程继续执行的效果;该信号量调用Reset方法时,将事件状态设置为“未触发”,所有等待该事件的线程(线程中调用该信号量WaitOne方法的地方)都会被阻塞,直到事件状态被设置为“已触发”,从而达到线程暂停执行的效果。