gpt4 book ai didi

c# - TaskCompletionSource 抛出 "An attempt was made to transition a task to a final state when it had already completed"

转载 作者:可可西里 更新时间:2023-11-01 07:51:45 30 4
gpt4 key购买 nike

我想使用 TaskCompletionSource 来包装 MyService 这是一个简单的服务:

public static Task<string> ProcessAsync(MyService service, int parameter)
{
var tcs = new TaskCompletionSource<string>();
//Every time ProccessAsync is called this assigns to Completed!
service.Completed += (sender, e)=>{ tcs.SetResult(e.Result); };
service.RunAsync(parameter);
return tcs.Task;
}

这段代码第一次运行良好。但是我第二次调用ProcessAsync 只是再次分配Completed 的事件处理程序(相同的service 变量每次都使用)因此它将执行两次!第二次它抛出这个异常:

attempt transition task final state when already completed

我不确定,我是否应该像这样将 tcs 声明为类级变量:

TaskCompletionSource<string> tcs;

public static Task<string> ProccessAsync(MyService service, int parameter)
{
tcs = new TaskCompletionSource<string>();
service.Completed -= completedHandler;
service.Completed += completedHandler;
return tcs.Task;
}

private void completedHandler(object sender, CustomEventArg e)
{
tcs.SetResult(e.Result);
}

我必须包装许多具有不同返回类型的方法,这样我就必须编写丢失的代码、变量、事件处理程序,所以我不确定这是否是这种情况下的最佳做法。那么有没有更好的方法来完成这项工作?

最佳答案

这里的问题是 Completed 事件会在每个操作上引发,但 TaskCompletionSource 只能完成一次。

您仍然可以使用本地 TaskCompletionSource(您应该这样做)。您只需在完成 TaskCompletionSource 之前注销回调。这样,将永远不会再次调用具有此特定 TaskCompletionSource 的特定回调:

public static Task<string> ProcessAsync(MyService service, int parameter)
{
var tcs = new TaskCompletionSource<string>();
EventHandler<CustomEventArg> callback = null;
callback = (sender, e) =>
{
service.Completed -= callback;
tcs.SetResult(e.Result);
};
service.Completed += callback;
service.RunAsync(parameter);
return tcs.Task;
}

这还将解决当您的服务保留对所有这些委托(delegate)的引用时可能出现的内存泄漏。

您应该记住,您不能同时运行多个这些操作。至少不会,除非您有办法匹配请求和响应。

关于c# - TaskCompletionSource 抛出 "An attempt was made to transition a task to a final state when it had already completed",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31787840/

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