Skip to content

Instantly share code, notes, and snippets.

@noseratio
Last active May 2, 2023 11:30
Show Gist options
  • Save noseratio/2a0fde1c3c233778ce945cb5b408c479 to your computer and use it in GitHub Desktop.
Save noseratio/2a0fde1c3c233778ce945cb5b408c479 to your computer and use it in GitHub Desktop.
Wrap an event as Task
/// <summary>
/// Wrap an event as Task
/// </summary>
/// <see href="https://stackoverflow.com/a/22798789/1768303"/>
public static async Task<TEventArgs> FromEvent<TEventHandler, TEventArgs>(
Func<Action<TEventArgs>, Action, Action<Exception>, TEventHandler> getHandler,
Action<TEventHandler> subscribe,
Action<TEventHandler> unsubscribe,
Action<Action<TEventArgs>, Action, Action<Exception>> initiate,
CancellationToken token = default) where TEventHandler : Delegate
{
var tcs = new TaskCompletionSource<TEventArgs>();
Action<TEventArgs> complete = args => tcs.TrySetResult(args);
Action cancel = () => tcs.TrySetCanceled();
Action<Exception> reject = ex => tcs.TrySetException(ex);
TEventHandler handler = getHandler(complete, cancel, reject);
subscribe(handler);
try
{
using (token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false))
{
initiate(complete, cancel, reject);
return await tcs.Task;
}
}
finally
{
unsubscribe(handler);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment