File: Async\AsynchronousOperationBlocker.cs
Web Access
Project: src\src\EditorFeatures\TestUtilities\Microsoft.CodeAnalysis.EditorFeatures.Test.Utilities.csproj (Microsoft.CodeAnalysis.EditorFeatures.Test.Utilities)
// 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.
 
#nullable disable
 
using System;
using System.Threading;
using Microsoft.CodeAnalysis;
 
namespace Roslyn.Test.Utilities
{
    public sealed class AsynchronousOperationBlocker : IDisposable
    {
        private readonly ManualResetEvent _waitHandle;
        private readonly object _lockObj = new();
        private bool _blocking;
        private bool _disposed;
 
        public AsynchronousOperationBlocker()
        {
            _waitHandle = new ManualResetEvent(false);
            _blocking = true;
        }
 
        public bool IsBlockingOperations
        {
            get
            {
                lock (_lockObj)
                {
                    return _blocking;
                }
            }
 
            private set
            {
                lock (_lockObj)
                {
                    if (_blocking == value)
                    {
                        return;
                    }
 
                    _blocking = value;
                    if (!_disposed)
                    {
                        if (_blocking)
                        {
                            _waitHandle.Reset();
                        }
                        else
                        {
                            _waitHandle.Set();
                        }
                    }
                }
            }
        }
 
        public void BlockOperations()
            => this.IsBlockingOperations = true;
 
        public void UnblockOperations()
            => this.IsBlockingOperations = false;
 
        public bool WaitIfBlocked(TimeSpan timeout)
        {
            if (_disposed)
            {
                FailFast.Fail("Badness");
            }
 
            return _waitHandle.WaitOne(timeout);
        }
 
        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
                _waitHandle.Dispose();
            }
        }
    }
}