app/BTCPayApp.Core/Helpers/AsyncExtensions.cs
2024-06-07 13:24:02 +02:00

67 lines
2.1 KiB
C#

using System.ComponentModel;
using System.Runtime.CompilerServices;
using NBitcoin;
namespace BTCPayApp.Core.Helpers;
public static class AsyncExtensions
{
public static async Task RunSync(this Task task)
{
task.GetAwaiter().GetResult();
}
public static async Task<T> RunSync<T>(this Task<T> task)
{
return task.GetAwaiter().GetResult();
}
/// <summary>
/// Allows a cancellation token to be awaited.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static CancellationTokenAwaiter GetAwaiter(this CancellationToken ct)
{
// return our special awaiter
return new CancellationTokenAwaiter
{
CancellationToken = ct
};
}
/// <summary>
/// The awaiter for cancellation tokens.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public struct CancellationTokenAwaiter : INotifyCompletion, ICriticalNotifyCompletion
{
public CancellationTokenAwaiter(CancellationToken cancellationToken)
{
CancellationToken = cancellationToken;
}
internal CancellationToken CancellationToken;
public object GetResult()
{
// this is called by compiler generated methods when the
// task has completed. Instead of returning a result, we
// just throw an exception.
if (IsCompleted) throw new OperationCanceledException();
else throw new InvalidOperationException("The cancellation token has not yet been cancelled.");
}
// called by compiler generated/.net internals to check
// if the task has completed.
public bool IsCompleted => CancellationToken.IsCancellationRequested;
// The compiler will generate stuff that hooks in
// here. We hook those methods directly into the
// cancellation token.
public void OnCompleted(Action continuation) =>
CancellationToken.Register(continuation);
public void UnsafeOnCompleted(Action continuation) =>
CancellationToken.Register(continuation);
}
}