gpt4 book ai didi

c# - 如何实现惰性 TaskCompletionSource?

转载 作者:太空狗 更新时间:2023-10-30 01:01:15 26 4
gpt4 key购买 nike

如果我的 TaskCompletionSource 公开的任务可能永远不会被调用,我如何才能推迟结果的计算,除非并且直到有人等待该任务?

例如,我想阻止其他异步执行线程,直到使用以下函数 WaitOneAsync 发出 ManualResetEvent 信号。我在 ThreadPool.RegisterWaitForSingleObject 的回调中完成 TaskCompleationSource,这在 WaitHandle 发出信号时发生。但是,如果没有人等待任务,那么我不想注册 WaitForSingleObject(如果在发出 WaitHandle 信号后等待任务,我也不想注册 WaitForSingleObject)。

我如何更改 WaitOneAsync,以便计算结果的工作(对 RegisterWaitForSingleObject)仅在有人等待 TaskCompleationSource.Task 之后发生?

我相信答案可能在于此处描述的自定义 TaskAwaiter Implement AsyncManualResetEvent using Lazy<T> to determine if the task has been awaited斯科特·张伯伦 (Scott Chamberlain),但我不能完全从他的例子到我的解决方案......:(

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;
}

最佳答案

正如 usr 所说,不可能对正在 awaited 的 Task 使用react。但是,如果您愿意使用自定义等待对象,那么您也可以。

一个简单的方法是使用 AsyncLazy from Stephen Cleary's AsyncEx :

private static Task<T> WaitOneAsyncImpl<T>(WaitHandle waitHandle, Func<T> result)
{
if (waitHandle.WaitOne(0))
return Task.FromResult(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 tcs.Task;
}

public static AsyncLazy<T> WaitOneAsync<T>(this WaitHandle waitHandle, Func<T> result)
=> new AsyncLazy<T>(() => WaitOneAsyncImpl(waitHandle, result));

关于c# - 如何实现惰性 TaskCompletionSource?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40321261/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com