#if NET20 || NET30 || NET35 || NET40 || !NET_4_6 using System.Diagnostics; using System.Security; using System.Threading; using System.Threading.Tasks; namespace System.Runtime.CompilerServices { /// /// Provides a builder for asynchronous methods that return void. /// This type is intended for compiler use only. /// /// public struct AsyncVoidMethodBuilder : IAsyncMethodBuilder { /// /// The synchronization context associated with this operation. /// private readonly SynchronizationContext _synchronizationContext; /// /// State related to the IAsyncStateMachine. /// private AsyncMethodBuilderCore _coreState; /// /// An object used by the debugger to uniquely identify this builder. Lazily initialized. /// private object _objectIdForDebugger; /// /// Non-zero if PreventUnobservedTaskExceptions has already been invoked. /// private static int _preventUnobservedTaskExceptionsInvoked; /// /// Gets an object that may be used to uniquely identify this builder to the debugger. /// /// /// /// /// This property lazily instantiates the ID in a non-thread-safe manner. /// It must only be used by the debugger and only in a single-threaded manner. /// /// private object ObjectIdForDebugger { get { return _objectIdForDebugger ?? (_objectIdForDebugger = new object()); } } /// /// Temporary support for disabling crashing if tasks go unobserved. /// static AsyncVoidMethodBuilder() { try { PreventUnobservedTaskExceptions(); } catch (Exception ex) { GC.KeepAlive(ex); } } /// /// Initializes the . /// /// The synchronizationContext associated with this operation. This may be null. private AsyncVoidMethodBuilder(SynchronizationContext synchronizationContext) { _synchronizationContext = synchronizationContext; if (synchronizationContext != null) { synchronizationContext.OperationStarted(); } _coreState = new AsyncMethodBuilderCore(); _objectIdForDebugger = null; } /// /// Registers with UnobservedTaskException to suppress exception crashing. /// internal static void PreventUnobservedTaskExceptions() { if (Interlocked.CompareExchange(ref _preventUnobservedTaskExceptionsInvoked, 1, 0) != 0) { return; } TaskScheduler.UnobservedTaskException += (s, e) => e.SetObserved(); } /// /// Initializes a new . /// /// /// /// The initialized . /// public static AsyncVoidMethodBuilder Create() { return new AsyncVoidMethodBuilder(SynchronizationContext.Current); } /// /// Initiates the builder's execution with the associated state machine. /// /// Specifies the type of the state machine.The state machine instance, passed by reference.The argument was null (Nothing in Visual Basic). [DebuggerStepThrough] public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { _coreState.Start(ref stateMachine); } /// /// Associates the builder with the state machine it represents. /// /// The heap-allocated state machine object.The argument was null (Nothing in Visual Basic).The builder is incorrectly initialized. public void SetStateMachine(IAsyncStateMachine stateMachine) { _coreState.SetStateMachine(stateMachine); } void IAsyncMethodBuilder.PreBoxInitialization() { } /// /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. /// /// /// Specifies the type of the awaiter.Specifies the type of the state machine.The awaiter.The state machine. public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { try { var completionAction = _coreState.GetCompletionAction(ref this, ref stateMachine); awaiter.OnCompleted(completionAction); } catch (Exception ex) { AsyncMethodBuilderCore.ThrowOnContext(ex, null); } } /// /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. /// /// /// Specifies the type of the awaiter.Specifies the type of the state machine.The awaiter.The state machine. [SecuritySafeCritical] public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { try { var completionAction = _coreState.GetCompletionAction(ref this, ref stateMachine); awaiter.UnsafeOnCompleted(completionAction); } catch (Exception ex) { AsyncMethodBuilderCore.ThrowOnContext(ex, null); } } /// /// Completes the method builder successfully. /// public void SetResult() { if (_synchronizationContext == null) { return; } NotifySynchronizationContextOfCompletion(); } /// /// Faults the method builder with an exception. /// /// The exception that is the cause of this fault.The argument is null (Nothing in Visual Basic).The builder is not initialized. public void SetException(Exception exception) { if (exception == null) { throw new ArgumentNullException("exception"); } if (_synchronizationContext != null) { try { AsyncMethodBuilderCore.ThrowOnContext(exception, _synchronizationContext); } finally { NotifySynchronizationContextOfCompletion(); } } else { AsyncMethodBuilderCore.ThrowOnContext(exception, null); } } /// /// Notifies the current synchronization context that the operation completed. /// private void NotifySynchronizationContextOfCompletion() { try { _synchronizationContext.OperationCompleted(); } catch (Exception ex) { AsyncMethodBuilderCore.ThrowOnContext(ex, null); } } } } #endif