【发布时间】:2016-10-30 04:57:36
【问题描述】:
如果我的 TaskCompletionSource 公开的任务可能永远不会被调用,我该如何推迟计算结果,除非有人等待该任务?
例如,我想阻止其他异步执行线程,直到使用以下函数 WaitOneAsync 发出 ManualResetEvent 信号。我在发出 WaitHandle 信号时发生的 ThreadPool.RegisterWaitForSingleObject 回调中完成了 TaskCompleationSource。但是,如果没有人等待任务,那么我不想 RegisterWaitForSingleObject(如果在 WaitHandle 发出信号后等待任务,我也不想 RegisterWaitForSingleObject)。
如何更改 WaitOneAsync 以便计算结果到 RegisterWaitForSingleObject 的工作仅在有人等待 TaskCompleationSource.Task 之后发生?
我相信答案可能在于一个自定义 TaskAwaiter,正如 Scott Chamberlain 在 Implement AsyncManualResetEvent using Lazy<T> to determine if the task has been awaited 中所描述的那样,但我不能完全从他的例子中得到我的解决方案...... :(
public static async Task<T> WaitOneAsync<T>(this WaitHandle waitHandle, Func<T> result) {
var tcs = new TaskCompletionSource<T>();
RegisteredWaitHandle rwh = null;
rwh = ThreadPool.RegisterWaitForSingleObject(
waitObject: waitHandle,
callBack: (s, t) => {
rwh.Unregister(null);
tcs.TrySetResult(result());
},
state: null,
millisecondsTimeOutInterval: -1,
executeOnlyOnce: true
);
return await tcs.Task;
}
【问题讨论】:
标签: c# multithreading async-await task-parallel-library lazy-evaluation