Pārlūkot izejas kodu

Remove awaitable interfaces.

Bart De Smet 5 gadi atpakaļ
vecāks
revīzija
37de346195

+ 44 - 31
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/AsyncScheduler.cs

@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT License.
 // See the LICENSE file in the project root for more information. 
 
+using System.Runtime.CompilerServices;
 using System.Runtime.ExceptionServices;
 using System.Threading;
 using System.Threading.Tasks;
@@ -10,7 +11,7 @@ namespace System.Reactive.Concurrency
 {
     public static class AsyncScheduler
     {
-        public static IAwaitable RendezVous(this IAsyncScheduler scheduler, CancellationToken token = default)
+        public static RendezVousAwaitable RendezVous(this IAsyncScheduler scheduler, CancellationToken token = default)
         {
             if (scheduler == null)
                 throw new ArgumentNullException(nameof(scheduler));
@@ -20,7 +21,7 @@ namespace System.Reactive.Concurrency
             return new RendezVousAwaitable(scheduler, token);
         }
 
-        public static IAwaitable RendezVous(this Task task, IAsyncScheduler scheduler, CancellationToken token = default)
+        public static TaskAwaitable RendezVous(this Task task, IAsyncScheduler scheduler, CancellationToken token = default)
         {
             if (task == null)
                 throw new ArgumentNullException(nameof(task));
@@ -30,7 +31,7 @@ namespace System.Reactive.Concurrency
             return new TaskAwaitable(task, continueOnCapturedContext: false, scheduler, token);
         }
 
-        public static IAwaitable<T> RendezVous<T>(this Task<T> task, IAsyncScheduler scheduler, CancellationToken token = default)
+        public static TaskAwaitable<T> RendezVous<T>(this Task<T> task, IAsyncScheduler scheduler, CancellationToken token = default)
         {
             if (task == null)
                 throw new ArgumentNullException(nameof(task));
@@ -40,7 +41,7 @@ namespace System.Reactive.Concurrency
             return new TaskAwaitable<T>(task, continueOnCapturedContext: false, scheduler, token);
         }
 
-        public static IAwaitable RendezVous(this ValueTask task, IAsyncScheduler scheduler, CancellationToken token = default)
+        public static ValueTaskAwaitable RendezVous(this ValueTask task, IAsyncScheduler scheduler, CancellationToken token = default)
         {
             if (scheduler == null)
                 throw new ArgumentNullException(nameof(scheduler));
@@ -48,7 +49,7 @@ namespace System.Reactive.Concurrency
             return new ValueTaskAwaitable(task, continueOnCapturedContext: false, scheduler, token);
         }
 
-        public static IAwaitable<T> RendezVous<T>(this ValueTask<T> task, IAsyncScheduler scheduler, CancellationToken token = default)
+        public static ValueTaskAwaitable<T> RendezVous<T>(this ValueTask<T> task, IAsyncScheduler scheduler, CancellationToken token = default)
         {
             if (scheduler == null)
                 throw new ArgumentNullException(nameof(scheduler));
@@ -196,11 +197,10 @@ namespace System.Reactive.Concurrency
             }
         }
 
-        private sealed class RendezVousAwaitable : IAwaitable, IAwaiter // PERF: Can we avoid these allocations?
+        public readonly struct RendezVousAwaitable
         {
             private readonly IAsyncScheduler _scheduler;
             private readonly CancellationToken _token;
-            private ExceptionDispatchInfo _error;
 
             public RendezVousAwaitable(IAsyncScheduler scheduler, CancellationToken token)
             {
@@ -208,42 +208,55 @@ namespace System.Reactive.Concurrency
                 _token = token;
             }
 
-            public bool IsCompleted { get; private set; }
+            public RendezVousAwaiter GetAwaiter() => new RendezVousAwaiter(_scheduler, _token);
 
-            public IAwaiter GetAwaiter() => this;
-
-            public void GetResult()
+            public sealed class RendezVousAwaiter : INotifyCompletion
             {
-                if (!IsCompleted)
-                {
-                    throw new InvalidOperationException(); // REVIEW: No support for blocking.
-                }
+                private readonly IAsyncScheduler _scheduler;
+                private readonly CancellationToken _token;
+                private ExceptionDispatchInfo _error;
 
-                if (_error != null)
+                public RendezVousAwaiter(IAsyncScheduler scheduler, CancellationToken token)
                 {
-                    _error.Throw();
+                    _scheduler = scheduler;
+                    _token = token;
                 }
-            }
 
-            public void OnCompleted(Action continuation)
-            {
-                var t = _scheduler.ExecuteAsync(ct =>
+                public bool IsCompleted { get; private set; }
+
+                public void GetResult()
                 {
-                    try
+                    if (!IsCompleted)
                     {
-                        continuation();
+                        throw new InvalidOperationException(); // REVIEW: No support for blocking.
                     }
-                    catch (Exception ex)
-                    {
-                        _error = ExceptionDispatchInfo.Capture(ex);
-                    }
-                    finally
+
+                    if (_error != null)
                     {
-                        IsCompleted = true;
+                        _error.Throw();
                     }
+                }
 
-                    return default;
-                }, _token);
+                public void OnCompleted(Action continuation)
+                {
+                    var t = _scheduler.ExecuteAsync(ct =>
+                    {
+                        try
+                        {
+                            continuation();
+                        }
+                        catch (Exception ex)
+                        {
+                            _error = ExceptionDispatchInfo.Capture(ex);
+                        }
+                        finally
+                        {
+                            IsCompleted = true;
+                        }
+
+                        return default;
+                    }, _token);
+                }
             }
         }
     }

+ 118 - 86
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Threading/Tasks/TaskAwaitable.cs

@@ -7,148 +7,180 @@ using System.Runtime.CompilerServices;
 
 namespace System.Threading.Tasks
 {
-    public sealed class TaskAwaitable : IAwaitable, IAwaiter
+    public readonly struct TaskAwaitable
     {
-        private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter _task;
+        private readonly Task _task;
+        private readonly bool _continueOnCapturedContext;
         private readonly IAsyncScheduler _scheduler;
         private readonly CancellationToken _token;
 
         public TaskAwaitable(Task task, bool continueOnCapturedContext, IAsyncScheduler scheduler, CancellationToken token)
         {
-            if (task == null)
-                throw new ArgumentNullException(nameof(task));
-
-            _task = task.ConfigureAwait(continueOnCapturedContext).GetAwaiter();
+            _task = task;
+            _continueOnCapturedContext = continueOnCapturedContext;
             _scheduler = scheduler;
             _token = token;
         }
 
-        public bool IsCompleted => _task.IsCompleted;
-
-        public IAwaiter GetAwaiter() => this;
+        public TaskAwaiter GetAwaiter() => new TaskAwaiter(_task.ConfigureAwait(_continueOnCapturedContext).GetAwaiter(), _scheduler, _token);
 
-        public void GetResult()
+        public readonly struct TaskAwaiter : INotifyCompletion
         {
-            _token.ThrowIfCancellationRequested();
+            private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter _awaiter;
+            private readonly IAsyncScheduler _scheduler;
+            private readonly CancellationToken _token;
 
-            _task.GetResult();
-        }
+            public TaskAwaiter(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter awaiter, IAsyncScheduler scheduler, CancellationToken token)
+            {
+                _awaiter = awaiter;
+                _scheduler = scheduler;
+                _token = token;
+            }
 
-        public void OnCompleted(Action continuation)
-        {
-            var cancel = default(IDisposable);
+            public bool IsCompleted => _awaiter.IsCompleted;
 
-            if (_token.CanBeCanceled)
+            public void GetResult()
             {
-                cancel = _token.Register(() =>
-                {
-                    Interlocked.Exchange(ref continuation, null)?.Invoke();
-                });
+                _token.ThrowIfCancellationRequested();
+
+                _awaiter.GetResult();
             }
 
-            try
+            public void OnCompleted(Action continuation)
             {
-                _task.OnCompleted(() =>
+                var cancel = default(IDisposable);
+
+                if (_token.CanBeCanceled)
                 {
-                    void Invoke()
+                    cancel = _token.Register(() =>
                     {
-                        cancel?.Dispose();
-
                         Interlocked.Exchange(ref continuation, null)?.Invoke();
-                    }
+                    });
+                }
 
-                    if (_scheduler != null)
+                try
+                {
+                    var scheduler = _scheduler;
+                    var token = _token;
+
+                    _awaiter.OnCompleted(() =>
                     {
-                        var t = _scheduler.ExecuteAsync(ct =>
+                        void Invoke()
                         {
-                            Invoke();
+                            cancel?.Dispose();
 
-                            return default;
-                        }, _token);
-                    }
-                    else
-                    {
-                        Invoke();
-                    }
-                });
-            }
-            catch
-            {
-                cancel?.Dispose();
-                throw;
+                            Interlocked.Exchange(ref continuation, null)?.Invoke();
+                        }
+
+                        if (scheduler != null)
+                        {
+                            var t = scheduler.ExecuteAsync(ct =>
+                            {
+                                Invoke();
+
+                                return default;
+                            }, token);
+                        }
+                        else
+                        {
+                            Invoke();
+                        }
+                    });
+                }
+                catch
+                {
+                    cancel?.Dispose();
+                    throw;
+                }
             }
         }
     }
 
-    public sealed class TaskAwaitable<T> : IAwaitable<T>, IAwaiter<T>
+    public readonly struct TaskAwaitable<T>
     {
-        private readonly ConfiguredTaskAwaitable<T>.ConfiguredTaskAwaiter _task;
+        private readonly Task<T> _task;
+        private readonly bool _continueOnCapturedContext;
         private readonly IAsyncScheduler _scheduler;
         private readonly CancellationToken _token;
 
         public TaskAwaitable(Task<T> task, bool continueOnCapturedContext, IAsyncScheduler scheduler, CancellationToken token)
         {
-            if (task == null)
-                throw new ArgumentNullException(nameof(task));
-
-            _task = task.ConfigureAwait(continueOnCapturedContext).GetAwaiter();
+            _task = task;
+            _continueOnCapturedContext = continueOnCapturedContext;
             _scheduler = scheduler;
             _token = token;
         }
 
-        public bool IsCompleted => _task.IsCompleted;
-
-        public IAwaiter<T> GetAwaiter() => this;
+        public TaskAwaiter GetAwaiter() => new TaskAwaiter(_task.ConfigureAwait(_continueOnCapturedContext).GetAwaiter(), _scheduler, _token);
 
-        public T GetResult()
+        public readonly struct TaskAwaiter : INotifyCompletion
         {
-            _token.ThrowIfCancellationRequested();
+            private readonly ConfiguredTaskAwaitable<T>.ConfiguredTaskAwaiter _awaiter;
+            private readonly IAsyncScheduler _scheduler;
+            private readonly CancellationToken _token;
 
-            return _task.GetResult();
-        }
+            public TaskAwaiter(ConfiguredTaskAwaitable<T>.ConfiguredTaskAwaiter awaiter, IAsyncScheduler scheduler, CancellationToken token)
+            {
+                _awaiter = awaiter;
+                _scheduler = scheduler;
+                _token = token;
+            }
 
-        public void OnCompleted(Action continuation)
-        {
-            var cancel = default(IDisposable);
+            public bool IsCompleted => _awaiter.IsCompleted;
 
-            if (_token.CanBeCanceled)
+            public T GetResult()
             {
-                cancel = _token.Register(() =>
-                {
-                    Interlocked.Exchange(ref continuation, null)?.Invoke();
-                });
+                _token.ThrowIfCancellationRequested();
+
+                return _awaiter.GetResult();
             }
 
-            try
+            public void OnCompleted(Action continuation)
             {
-                _task.OnCompleted(() =>
+                var cancel = default(IDisposable);
+
+                if (_token.CanBeCanceled)
                 {
-                    void Invoke()
+                    cancel = _token.Register(() =>
                     {
-                        cancel?.Dispose();
-
                         Interlocked.Exchange(ref continuation, null)?.Invoke();
-                    }
+                    });
+                }
 
-                    if (_scheduler != null)
+                try
+                {
+                    var scheduler = _scheduler;
+                    var token = _token;
+
+                    _awaiter.OnCompleted(() =>
                     {
-                        var t = _scheduler.ExecuteAsync(ct =>
+                        void Invoke()
                         {
-                            Invoke();
+                            cancel?.Dispose();
 
-                            return default;
-                        }, _token);
-                    }
-                    else
-                    {
-                        Invoke();
-                    }
-                });
-            }
-            catch
-            {
-                cancel?.Dispose();
-                throw;
+                            Interlocked.Exchange(ref continuation, null)?.Invoke();
+                        }
+
+                        if (scheduler != null)
+                        {
+                            var t = scheduler.ExecuteAsync(ct =>
+                            {
+                                Invoke();
+
+                                return default;
+                            }, token);
+                        }
+                        else
+                        {
+                            Invoke();
+                        }
+                    });
+                }
+                catch
+                {
+                    cancel?.Dispose();
+                    throw;
+                }
             }
         }
     }

+ 118 - 86
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Threading/Tasks/ValueTaskAwaitable.cs

@@ -7,148 +7,180 @@ using System.Runtime.CompilerServices;
 
 namespace System.Threading.Tasks
 {
-    public sealed class ValueTaskAwaitable : IAwaitable, IAwaiter
+    public readonly struct ValueTaskAwaitable
     {
-        private readonly ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter _task;
+        private readonly ValueTask _task;
+        private readonly bool _continueOnCapturedContext;
         private readonly IAsyncScheduler _scheduler;
         private readonly CancellationToken _token;
 
         public ValueTaskAwaitable(ValueTask task, bool continueOnCapturedContext, IAsyncScheduler scheduler, CancellationToken token)
         {
-            if (task == null)
-                throw new ArgumentNullException(nameof(task));
-
-            _task = task.ConfigureAwait(continueOnCapturedContext).GetAwaiter();
+            _task = task;
+            _continueOnCapturedContext = continueOnCapturedContext;
             _scheduler = scheduler;
             _token = token;
         }
 
-        public bool IsCompleted => _task.IsCompleted;
-
-        public IAwaiter GetAwaiter() => this;
+        public ValueTaskAwaiter GetAwaiter() => new ValueTaskAwaiter(_task.ConfigureAwait(_continueOnCapturedContext).GetAwaiter(), _scheduler, _token);
 
-        public void GetResult()
+        public readonly struct ValueTaskAwaiter : INotifyCompletion
         {
-            _token.ThrowIfCancellationRequested();
+            private readonly ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter _awaiter;
+            private readonly IAsyncScheduler _scheduler;
+            private readonly CancellationToken _token;
 
-            _task.GetResult();
-        }
+            public ValueTaskAwaiter(ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter, IAsyncScheduler scheduler, CancellationToken token)
+            {
+                _awaiter = awaiter;
+                _scheduler = scheduler;
+                _token = token;
+            }
 
-        public void OnCompleted(Action continuation)
-        {
-            var cancel = default(IDisposable);
+            public bool IsCompleted => _awaiter.IsCompleted;
 
-            if (_token.CanBeCanceled)
+            public void GetResult()
             {
-                cancel = _token.Register(() =>
-                {
-                    Interlocked.Exchange(ref continuation, null)?.Invoke();
-                });
+                _token.ThrowIfCancellationRequested();
+
+                _awaiter.GetResult();
             }
 
-            try
+            public void OnCompleted(Action continuation)
             {
-                _task.OnCompleted(() =>
+                var cancel = default(IDisposable);
+
+                if (_token.CanBeCanceled)
                 {
-                    void Invoke()
+                    cancel = _token.Register(() =>
                     {
-                        cancel?.Dispose();
-
                         Interlocked.Exchange(ref continuation, null)?.Invoke();
-                    }
+                    });
+                }
 
-                    if (_scheduler != null)
+                try
+                {
+                    var scheduler = _scheduler;
+                    var token = _token;
+
+                    _awaiter.OnCompleted(() =>
                     {
-                        var t = _scheduler.ExecuteAsync(ct =>
+                        void Invoke()
                         {
-                            Invoke();
+                            cancel?.Dispose();
 
-                            return default;
-                        }, _token);
-                    }
-                    else
-                    {
-                        Invoke();
-                    }
-                });
-            }
-            catch
-            {
-                cancel?.Dispose();
-                throw;
+                            Interlocked.Exchange(ref continuation, null)?.Invoke();
+                        }
+
+                        if (scheduler != null)
+                        {
+                            var t = scheduler.ExecuteAsync(ct =>
+                            {
+                                Invoke();
+
+                                return default;
+                            }, token);
+                        }
+                        else
+                        {
+                            Invoke();
+                        }
+                    });
+                }
+                catch
+                {
+                    cancel?.Dispose();
+                    throw;
+                }
             }
         }
     }
 
-    public sealed class ValueTaskAwaitable<T> : IAwaitable<T>, IAwaiter<T>
+    public readonly struct ValueTaskAwaitable<T>
     {
-        private readonly ConfiguredValueTaskAwaitable<T>.ConfiguredValueTaskAwaiter _task;
+        private readonly ValueTask<T> _task;
+        private readonly bool _continueOnCapturedContext;
         private readonly IAsyncScheduler _scheduler;
         private readonly CancellationToken _token;
 
         public ValueTaskAwaitable(ValueTask<T> task, bool continueOnCapturedContext, IAsyncScheduler scheduler, CancellationToken token)
         {
-            if (task == null)
-                throw new ArgumentNullException(nameof(task));
-
-            _task = task.ConfigureAwait(continueOnCapturedContext).GetAwaiter();
+            _task = task;
+            _continueOnCapturedContext = continueOnCapturedContext;
             _scheduler = scheduler;
             _token = token;
         }
 
-        public bool IsCompleted => _task.IsCompleted;
-
-        public IAwaiter<T> GetAwaiter() => this;
+        public ValueTaskAwaiter GetAwaiter() => new ValueTaskAwaiter(_task.ConfigureAwait(_continueOnCapturedContext).GetAwaiter(), _scheduler, _token);
 
-        public T GetResult()
+        public readonly struct ValueTaskAwaiter : INotifyCompletion
         {
-            _token.ThrowIfCancellationRequested();
+            private readonly ConfiguredValueTaskAwaitable<T>.ConfiguredValueTaskAwaiter _awaiter;
+            private readonly IAsyncScheduler _scheduler;
+            private readonly CancellationToken _token;
 
-            return _task.GetResult();
-        }
+            public ValueTaskAwaiter(ConfiguredValueTaskAwaitable<T>.ConfiguredValueTaskAwaiter awaiter, IAsyncScheduler scheduler, CancellationToken token)
+            {
+                _awaiter = awaiter;
+                _scheduler = scheduler;
+                _token = token;
+            }
 
-        public void OnCompleted(Action continuation)
-        {
-            var cancel = default(IDisposable);
+            public bool IsCompleted => _awaiter.IsCompleted;
 
-            if (_token.CanBeCanceled)
+            public T GetResult()
             {
-                cancel = _token.Register(() =>
-                {
-                    Interlocked.Exchange(ref continuation, null)?.Invoke();
-                });
+                _token.ThrowIfCancellationRequested();
+
+                return _awaiter.GetResult();
             }
 
-            try
+            public void OnCompleted(Action continuation)
             {
-                _task.OnCompleted(() =>
+                var cancel = default(IDisposable);
+
+                if (_token.CanBeCanceled)
                 {
-                    void Invoke()
+                    cancel = _token.Register(() =>
                     {
-                        cancel?.Dispose();
-
                         Interlocked.Exchange(ref continuation, null)?.Invoke();
-                    }
+                    });
+                }
 
-                    if (_scheduler != null)
+                try
+                {
+                    var scheduler = _scheduler;
+                    var token = _token;
+
+                    _awaiter.OnCompleted(() =>
                     {
-                        var t = _scheduler.ExecuteAsync(ct =>
+                        void Invoke()
                         {
-                            Invoke();
+                            cancel?.Dispose();
 
-                            return default;
-                        }, _token);
-                    }
-                    else
-                    {
-                        Invoke();
-                    }
-                });
-            }
-            catch
-            {
-                cancel?.Dispose();
-                throw;
+                            Interlocked.Exchange(ref continuation, null)?.Invoke();
+                        }
+
+                        if (scheduler != null)
+                        {
+                            var t = scheduler.ExecuteAsync(ct =>
+                            {
+                                Invoke();
+
+                                return default;
+                            }, token);
+                        }
+                        else
+                        {
+                            Invoke();
+                        }
+                    });
+                }
+                catch
+                {
+                    cancel?.Dispose();
+                    throw;
+                }
             }
         }
     }

+ 2 - 2
AsyncRx.NET/System.Reactive.Async.Subjects/System/Reactive/FastImmediateAsyncObserver.cs

@@ -19,9 +19,9 @@ namespace System.Reactive
 
         public override ValueTask DisposeAsync() => _disposable.DisposeAsync();
 
-        protected override IAwaitable RendezVous(ValueTask task) => new ValueTaskAwaitable(task, false, null, CancellationToken.None);
+        protected override ValueTaskAwaitable RendezVous(ValueTask task) => new ValueTaskAwaitable(task, continueOnCapturedContext: false, scheduler: null, CancellationToken.None);
 
-        protected override IAwaitable<R> RendezVous<R>(ValueTask<R> task) => new ValueTaskAwaitable<R>(task, false, null, CancellationToken.None);
+        protected override ValueTaskAwaitable<R> RendezVous<R>(ValueTask<R> task) => new ValueTaskAwaitable<R>(task, continueOnCapturedContext: false, scheduler: null, CancellationToken.None);
 
         protected override ValueTask ScheduleAsync() => RunAsync(_disposable.Token);
     }

+ 2 - 2
AsyncRx.NET/System.Reactive.Async.Subjects/System/Reactive/ScheduledAsyncObserver.cs

@@ -23,9 +23,9 @@ namespace System.Reactive
 
         public override ValueTask DisposeAsync() => _disposable.DisposeAsync();
 
-        protected override IAwaitable RendezVous(ValueTask task) => new ValueTaskAwaitable(task, false, _scheduler, CancellationToken.None);
+        protected override ValueTaskAwaitable RendezVous(ValueTask task) => new ValueTaskAwaitable(task, continueOnCapturedContext: false, _scheduler, CancellationToken.None);
 
-        protected override IAwaitable<R> RendezVous<R>(ValueTask<R> task) => new ValueTaskAwaitable<R>(task, false, _scheduler, CancellationToken.None);
+        protected override ValueTaskAwaitable<R> RendezVous<R>(ValueTask<R> task) => new ValueTaskAwaitable<R>(task, continueOnCapturedContext: false, _scheduler, CancellationToken.None);
 
         protected override async ValueTask ScheduleAsync()
         {

+ 2 - 2
AsyncRx.NET/System.Reactive.Async.Subjects/System/Reactive/ScheduledAsyncObserverBase.cs

@@ -148,9 +148,9 @@ namespace System.Reactive
             }
         }
 
-        protected abstract IAwaitable RendezVous(ValueTask task);
+        protected abstract ValueTaskAwaitable RendezVous(ValueTask task);
 
-        protected abstract IAwaitable<R> RendezVous<R>(ValueTask<R> task);
+        protected abstract ValueTaskAwaitable<R> RendezVous<R>(ValueTask<R> task);
 
         public abstract ValueTask DisposeAsync();
     }

+ 0 - 16
AsyncRx.NET/System.Reactive.Bcl/System/IAwaitable.cs

@@ -1,16 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT License.
-// See the LICENSE file in the project root for more information. 
-
-namespace System
-{
-    public interface IAwaitable
-    {
-        IAwaiter GetAwaiter();
-    }
-
-    public interface IAwaitable<T>
-    {
-        IAwaiter<T> GetAwaiter();
-    }
-}

+ 0 - 20
AsyncRx.NET/System.Reactive.Bcl/System/IAwaiter.cs

@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT License.
-// See the LICENSE file in the project root for more information. 
-
-using System.Runtime.CompilerServices;
-
-namespace System
-{
-    public interface IAwaiter : INotifyCompletion
-    {
-        bool IsCompleted { get; }
-        void GetResult();
-    }
-
-    public interface IAwaiter<T> : INotifyCompletion
-    {
-        bool IsCompleted { get; }
-        T GetResult();
-    }
-}