#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