mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-24 12:06:34 +00:00
58 lines
2.6 KiB
C#
58 lines
2.6 KiB
C#
using System.Runtime.CompilerServices;
|
|
|
|
namespace Daybreak.Shared.Models.Async;
|
|
|
|
/// <summary>
|
|
/// Represents an abstract asynchronous operation that can report progress and be canceled.
|
|
/// Constructed using <see cref="ProgressAsyncOperation.Create{T}(Task{T}, CancellationToken)"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Services should return <see cref="IProgressAsyncOperation{T}"/> so that consumers can monitor progress and await the result.
|
|
/// <see cref="ProgressChanged"/> event is raised whenever progress is reported via the <see cref="IProgress{T}.Report(T)"/> method. The operation can be awaited and will complete when the underlying task completes.
|
|
/// </remarks>
|
|
public sealed class ProgressAsyncOperation<T> : IProgressAsyncOperation<T>
|
|
{
|
|
private readonly Progress<ProgressUpdate> progress = new();
|
|
private readonly Task<T> task;
|
|
private readonly CancellationTokenSource cancellationTokenSource;
|
|
|
|
public event EventHandler<ProgressUpdate>? ProgressChanged;
|
|
public ProgressUpdate? CurrentProgress { get; private set; }
|
|
|
|
public bool IsCompleted => this.task.IsCompleted;
|
|
public bool IsCanceled => this.task.IsCanceled;
|
|
public bool IsFaulted => this.task.IsFaulted;
|
|
public CancellationToken CancellationToken => this.cancellationTokenSource.Token;
|
|
|
|
internal ProgressAsyncOperation(Func<Progress<ProgressUpdate>, Task<T>> wrappedTaskWithProgress, CancellationToken cancellationToken)
|
|
{
|
|
this.progress.ProgressChanged += (s, e) =>
|
|
{
|
|
this.CurrentProgress = e;
|
|
this.ProgressChanged?.Invoke(this, e);
|
|
};
|
|
|
|
this.task = wrappedTaskWithProgress(this.progress);
|
|
this.cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
|
}
|
|
|
|
public TaskAwaiter<T> GetAwaiter()
|
|
{
|
|
return this.task.GetAwaiter();
|
|
}
|
|
}
|
|
|
|
public static class ProgressAsyncOperation
|
|
{
|
|
/// <summary>
|
|
/// Creates a new <see cref="ProgressAsyncOperation{T}"/> instance that wraps the provided task and cancellation token and returns an awaitable that reports progress.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Inside the task factory, progress can be reported by calling the <see cref="IProgress{T}.Report(T)"/> method on the provided <see cref="IProgress{ProgressUpdate}"/> instance.
|
|
/// </remarks>
|
|
public static ProgressAsyncOperation<T> Create<T>(Func<IProgress<ProgressUpdate>, Task<T>> wrappedTaskWithProgress, CancellationToken cancellationToken)
|
|
{
|
|
return new ProgressAsyncOperation<T>(wrappedTaskWithProgress, cancellationToken);
|
|
}
|
|
}
|