| File: System\ComponentModel\AsyncOperation.cs | Web Access |
| Project: src\runtime\src\libraries\System.ComponentModel.EventBasedAsync\src\System.ComponentModel.EventBasedAsync.csproj (System.ComponentModel.EventBasedAsync) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Threading; namespace System.ComponentModel { public sealed class AsyncOperation { private readonly SynchronizationContext _syncContext; private bool _alreadyCompleted; /// <summary> /// Constructor. Protected to avoid unwitting usage - AsyncOperation objects /// are typically created by AsyncOperationManager calling CreateOperation. /// </summary> private AsyncOperation(object? userSuppliedState, SynchronizationContext syncContext) { UserSuppliedState = userSuppliedState; _syncContext = syncContext; _alreadyCompleted = false; _syncContext.OperationStarted(); } /// <summary> /// Destructor. Guarantees that sync context will always get notified of completion. /// </summary> ~AsyncOperation() { if (!_alreadyCompleted && _syncContext != null) { _syncContext.OperationCompleted(); } } public object? UserSuppliedState { get; } public SynchronizationContext SynchronizationContext { get { return _syncContext; } } public void Post(SendOrPostCallback d, object? arg) { PostCore(d, arg, markCompleted: false); } public void PostOperationCompleted(SendOrPostCallback d, object? arg) { PostCore(d, arg, markCompleted: true); OperationCompletedCore(); } public void OperationCompleted() { VerifyNotCompleted(); _alreadyCompleted = true; OperationCompletedCore(); } private void PostCore(SendOrPostCallback d, object? arg, bool markCompleted) { VerifyNotCompleted(); ArgumentNullException.ThrowIfNull(d); if (markCompleted) { // This call is in response to a PostOperationCompleted. As such, we need to mark // _alreadyCompleted as true so that subsequent attempts to use this instance will // fail appropriately. And we need to do that before we queue the callback, as // that callback could itself trigger additional attempts to use this instance. _alreadyCompleted = true; } _syncContext.Post(d, arg); } private void OperationCompletedCore() { try { _syncContext.OperationCompleted(); } finally { GC.SuppressFinalize(this); } } private void VerifyNotCompleted() { if (_alreadyCompleted) { throw new InvalidOperationException(SR.Async_OperationAlreadyCompleted); } } /// <summary> /// Only for use by AsyncOperationManager to create new AsyncOperation objects /// </summary> internal static AsyncOperation CreateOperation(object? userSuppliedState, SynchronizationContext syncContext) { AsyncOperation newOp = new AsyncOperation(userSuppliedState, syncContext); return newOp; } } }