How to write an “awaitable” method?

后端 未结 6 1880
南笙
南笙 2020-12-07 13:20

I\'m finally looking into the async & await keywords, which I kind of "get", but all the examples I\'ve seen call async methods in the .Net framework, e.g. thi

6条回答
  •  攒了一身酷
    2020-12-07 13:34

    If you don't want to use a Task, you may write a completely customized awaitable object. Such object is one implementing a method GetAwaiter () returning an object implementing INotifyCompletion, which can be the object itself.

    More: INotifyCompletion

    The awaiter implements:

    • IsCompleted is get the state
    • GetResult () to get the result
    • OnCompleted (Action continuation) to set the continuation delegate.

    The awaitable object contains some method for actual payload (e.g. below, the method is Run).

    class Program {
        // Need to change the declaration of Main() in order to use 'await'
        static async Task Main () {
            // Create a custom awaitable object
            MyAwaitable awaitable = new MyAwaitable ();
    
            // Run awaitable payload, ignore returned Task
            _ = awaitable.Run ();
    
            // Do some other tasks while awaitable is running
            Console.WriteLine ("Waiting for completion...");
    
            // Wait for completion
            await awaitable;
    
            Console.WriteLine ("The long operation is now complete. " + awaitable.GetResult());
        }
    }
    
    public class MyAwaitable : INotifyCompletion {
        // Fields
        private Action continuation = null;
        private string result = string.Empty;
    
        // Make this class awaitable
        public MyAwaitable GetAwaiter () { return this; }
    
        // Implementation of INotifyCompletion for the self-awaiter
        public bool IsCompleted { get; set; }
        public string GetResult () { return result; }
        public void OnCompleted (Action continuation) {
            // Store continuation delegate
            this.continuation = continuation;
            Console.WriteLine ("Continuation set");
        }
    
        // Payload to run
        public async Task Run () {
            Console.WriteLine ("Computing result...");
    
            // Wait 2 seconds
            await Task.Delay (2000);
            result = "The result is 10";
    
            // Set completed
            IsCompleted = true;
    
            Console.WriteLine ("Result available");
    
            // Continue with the continuation provided
            continuation?.Invoke ();
        }
    }
    

提交回复
热议问题