C# 多线程 03-使用线程池 05-在线程中使用等待事件处理器及超时
🏷️ 《C# 多线程》
本节将通过一个示例来展示如何在线程池中取消异步操作。
csharp
/// <summary>
/// 在线程中使用等待事件处理器及超时
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
RunOperations(TimeSpan.FromSeconds(5));
RunOperations(TimeSpan.FromSeconds(7));
}
static void RunOperations(TimeSpan workerOperationTimeout)
{
using (var evt = new ManualResetEvent(false))
using (var cts = new CancellationTokenSource())
{
Console.WriteLine($"注册一个超时操作...");
// 该方法允许我们将回调函数放入线程池中的队列中。
// 当提供的等待时间处理器收到信号或发生超时时,该回调函数将被调用。
// 第一个参数是等待对象(System.Threading.WaitHandle)
// 第二个参数是回调函数
// 第四个参数是超时事件
// 第五个参数为 true,表示仅执行一次
var worker = ThreadPool.RegisterWaitForSingleObject(evt,
(state, isTimeOut) => WorkerOperationWait(cts, isTimeOut),
null,
workerOperationTimeout,
true);
Console.WriteLine("开始执行一个长操作");
ThreadPool.QueueUserWorkItem(_ => WorkerOperation(cts.Token, evt));
Thread.Sleep(workerOperationTimeout.Add(TimeSpan.FromSeconds(2)));
worker.Unregister(evt);
}
}
static void WorkerOperation(CancellationToken token, ManualResetEvent evt)
{
for (int i = 0; i < 6; i++)
{
// 判断 token 是否已取消
if (token.IsCancellationRequested)
{
return;
}
Thread.Sleep(TimeSpan.FromSeconds(1));
}
// 6 秒后发送事件结束信号
evt.Set();
}
static void WorkerOperationWait(CancellationTokenSource cts, bool isTimeOut)
{
if (isTimeOut)
{
// 如果操作超时,则发送取消信号
cts.Cancel();
Console.WriteLine("操作超时且被取消");
} else
{
Console.WriteLine("操作执行成功");
}
}
打印结果
注册一个超时操作...
开始执行一个长操作
操作超时且被取消
注册一个超时操作...
开始执行一个长操作
操作执行成功
ThreadPool.RegisterWaitForSingleObject
方法的定义如下:
csharp
//
// 摘要:
// 注册一个等待 System.Threading.WaitHandle 的委托,并指定一个 System.TimeSpan 值来表示超时时间。
//
// 参数:
// waitObject:
// 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。
//
// callBack:
// 向 waitObject 参数发出信号时调用的 System.Threading.WaitOrTimerCallback 委托。
//
// state:
// 传递给委托的对象。
//
// timeout:
// System.TimeSpan 表示的超时时间。如果 timeout 为 0(零),则函数将测试对象的状态并立即返回。如果 timeout 为 -1,则函数的超时间隔永远不过期。
//
// executeOnlyOnce:
// 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。
//
// 返回结果:
// 封装本机句柄的 System.Threading.RegisteredWaitHandle。
//
// 异常:
// T:System.ArgumentOutOfRangeException:
// timeout 参数是小于 -1。
//
// T:System.NotSupportedException:
// timeout 参数是否大于 System.Int32.MaxValue。
[SecuritySafeCritical]
public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, TimeSpan timeout, bool executeOnlyOnce);