TaskCompletionSource throws “An attempt was made to transition a task to a final state when it had already completed”

后端 未结 3 1308
粉色の甜心
粉色の甜心 2021-02-07 08:06

I want to use TaskCompletionSource to wrap MyService which is a simple service:

public static Task ProcessAsync(MyService         


        
3条回答
  •  囚心锁ツ
    2021-02-07 08:56

    The issue here is that the Completed event is raised on each action but the TaskCompletionSource can only be completed once.

    You can still use a local TaskCompletionSource (and you should). You just need to unregister the callback before completing the TaskCompletionSource. That way this specific callback with this specific TaskCompletionSource will never be called again:

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

    This will also solve the possible memory leak that you have when your service keeps references to all these delegates.

    You should keep in mind though that you can't have multiple of these operations running concurrently. At least not unless you have a way to match requests and responses.

提交回复
热议问题