Non-Generic TaskCompletionSource or alternative

后端 未结 5 1067
时光说笑
时光说笑 2020-12-05 12:48

I\'m working with an alert window (Telerik WPF) that is normally displayed asynchronously ( code continues running while it is open) and I want to make it synchronous by usi

相关标签:
5条回答
  • 2020-12-05 12:59

    From @Kevin Kalitowski

    I found a Microsoft document, http://www.microsoft.com/en-us/download/details.aspx?id=19957, by Stephen Toub titled 'The Task-based Asynchronous pattern'

    There is an example in this document which I think deals with the issue as Kevin points out. This is the example:

    public static Task Delay(int millisecondsTimeout)
    {
        var tcs = new TaskCompletionSource<bool>();
        new Timer(self =>
        {
            ((IDisposable)self).Dispose();
            tcs.TrySetResult(true);
        }).Change(millisecondsTimeout, -1);
        return tcs.Task;
    }
    

    At first I thought it was not good because you can't directly add the "async" modifier to the method without a compilation message. But, if you change the method slightly, the method will compile with async/await:

    public async static Task Delay(int millisecondsTimeout)
    {
        var tcs = new TaskCompletionSource<bool>();
        new Timer(self =>
        {
            ((IDisposable)self).Dispose();
            tcs.TrySetResult(true);
        }).Change(millisecondsTimeout, -1);
        await tcs.Task;
    }
    

    Edit: at first I thought I'd gotten over the hump. But, when I ran the equivalent code in my app, this code just makes the app hang when it gets to await tcs.Task;. So, I still believe that this is a serious design flaw in the async/await c# syntax.

    0 讨论(0)
  • 2020-12-05 13:13

    Nito.AsyncEx implements a non-generic TaskCompletionSource class, credit to Mr @StephenCleary above.

    0 讨论(0)
  • 2020-12-05 13:14

    .NET 5 has a non-generic TaskCompletionSource.

    It was added in this pull request: https://github.com/dotnet/runtime/pull/37452/files#diff-4a72dcb26e2d643c337baef9f64312f3

    0 讨论(0)
  • 2020-12-05 13:20

    The method can be changed to:

    public Task ShowAlert(object message, string windowTitle)
    

    Task<bool> inherits from Task so you can return Task<bool> while only exposing Task to the caller

    Edit:

    I found a Microsoft document, http://www.microsoft.com/en-us/download/details.aspx?id=19957, by Stephen Toub titled 'The Task-based Asynchronous pattern' and it has the following excerpt that recommends this same pattern.

    There is no non-generic counterpart to TaskCompletionSource<TResult>. However, Task<TResult> derives from Task, and thus the generic TaskCompletionSource<TResult> can be used for I/O-bound methods that simply return a Task by utilizing a source with a dummy TResult (Boolean is a good default choice, and if a developer is concerned about a consumer of the Task downcasting it to a Task<TResult>, a private TResult type may be used)

    0 讨论(0)
  • 2020-12-05 13:22

    If you don't want to leak information, the common approach is to use TaskCompletionSource<object> and complete with a result of null. Then just return it as a Task.

    0 讨论(0)
提交回复
热议问题