| File: Process\RunningProcess.cs | Web Access |
| Project: src\sdk\src\Dotnet.Watch\Watch\Microsoft.DotNet.HotReload.Watch.csproj (Microsoft.DotNet.HotReload.Watch) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Microsoft.DotNet.Watch; internal sealed class RunningProcess( int id, Task<int> task, CancellationTokenSource exitedSource, CancellationTokenSource terminationSource) : IAsyncDisposable { private CancellationTokenSource? _terminationSource = terminationSource; /// <summary> /// Cancellation token triggered when the process exits. /// Stores the token to allow callers to use the token even after the source has been disposed. /// </summary> public readonly CancellationToken ExitedCancellationToken = exitedSource.Token; public Task<int> Task => task; public int Id => id; ValueTask IAsyncDisposable.DisposeAsync() => DisposeAsync(isExiting: false); public async ValueTask DisposeAsync(bool isExiting) { var terminationSource = Interlocked.Exchange(ref _terminationSource, null); ObjectDisposedException.ThrowIf(terminationSource == null, this); // do not await process termination since it's already in progress: if (!isExiting) { terminationSource.Cancel(); await task; } terminationSource.Dispose(); exitedSource.Cancel(); exitedSource.Dispose(); } /// <summary> /// Terminates the process if it hasn't terminated yet. /// Awating the task triggers OnExit handlers, which in turn call <see cref="DisposeAsync"/>. /// </summary> public Task TerminateAsync() { _terminationSource?.Cancel(); return task; } }