If the task opened by my TaskCompletionSource object can never be called, how can I reject the calculation of the result if and until someone completes the task?
For example, I want to block other asynchronous execution threads until a ManualResetEvent message is issued using the following WaitOneAsync function. I end the TaskCompleationSource in the ThreadPool.RegisterWaitForSingleObject callback, which happens when WaitHandle is signaled. But if no one is waiting for the task, then I do not want RegisterWaitForSingleObject (and I do not want RegisterWaitForSingleObject if the task is expected after the WaitHandle message).
How can I change WaitOneAsync so that the work of calculating the result in RegisterWaitForSingleObject is done only after someone waits for TaskCompleationSource.Task?
I believe that the answer may lie in a custom TaskAwaiter, as described here Implement AsyncManualResetEvent, using Lazy <T> to determine if Scott Chamberlain expected the task , but I can not get my solution from his example ... :(
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;
}
source
share