问题描述
我想等待带有超时和观察取消的手动重置事件.我想出了类似下面的东西.手动重置事件对象由我无法控制的 API 提供.有没有办法在不占用和阻止来自 ThreadPool 的线程的情况下实现这一点?
I'd like to await on a manual reset event with time-out and observing cancellation. I've come up with something like below. The manual reset event object is provided by an API beyond my control. Is there a way to make this happen without taking on and blocking a thread from ThreadPool?
static Task<bool> TaskFromWaitHandle(WaitHandle mre, int timeout, CancellationToken ct)
{
return Task.Run(() =>
{
bool s = WaitHandle.WaitAny(new WaitHandle[] { mre, ct.WaitHandle }, timeout) == 0;
ct.ThrowIfCancellationRequested();
return s;
}, ct);
}
// ...
if (await TaskFromWaitHandle(manualResetEvent, 1000, cts.Token))
{
// true if event was set
}
else
{
// false if timed out, exception if cancelled
}
显然,它很有意义 使用 RegisterWaitForSingleObject
.我试试看.
Apparently, it makes sense to use RegisterWaitForSingleObject
. I'll give it a try.
推荐答案
RegisterWaitForSingleObject
将等待合并到专用的等待线程上,每个线程可以等待多个句柄(具体来说,其中 63 个,即MAXIMUM_WAIT_OBJECTS
减一表示控制"句柄).
RegisterWaitForSingleObject
will combine waits onto dedicated waiter threads, each of which can wait on multiple handles (specifically, 63 of them, which is MAXIMUM_WAIT_OBJECTS
minus one for a "control" handle).
所以你应该能够使用这样的东西(警告:未经测试):
So you should be able to use something like this (warning: untested):
public static class WaitHandleExtensions
{
public static Task AsTask(this WaitHandle handle)
{
return AsTask(handle, Timeout.InfiniteTimeSpan);
}
public static Task AsTask(this WaitHandle handle, TimeSpan timeout)
{
var tcs = new TaskCompletionSource<object>();
var registration = ThreadPool.RegisterWaitForSingleObject(handle, (state, timedOut) =>
{
var localTcs = (TaskCompletionSource<object>)state;
if (timedOut)
localTcs.TrySetCanceled();
else
localTcs.TrySetResult(null);
}, tcs, timeout, executeOnlyOnce: true);
tcs.Task.ContinueWith((_, state) => ((RegisteredWaitHandle)state).Unregister(null), registration, TaskScheduler.Default);
return tcs.Task;
}
}
这篇关于将 ManualResetEvent 包装为等待任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!