Skip to content

Instantly share code, notes, and snippets.

@GeorgeTsiokos
Created December 6, 2016 18:05
Show Gist options
  • Save GeorgeTsiokos/1c3f975357b9db4c32b7b73b3f9aede4 to your computer and use it in GitHub Desktop.
Save GeorgeTsiokos/1c3f975357b9db4c32b7b73b3f9aede4 to your computer and use it in GitHub Desktop.
SynchronizationContextExtensions - Task<T> ExecuteAsync<T>
public static class SynchronizationContextExtensions {
public static Task<T> ExecuteAsync<T> (this SynchronizationContext synchronizationContext, Func<T> factory, CancellationToken cancellationToken = default (CancellationToken)) {
var state = new State<T> (factory,
cancellationToken);
synchronizationContext.Post (ExecuteAsync<T>,
state);
return state.Task;
}
private static void ExecuteAsync<T> (object state) {
var asyncState = (State<T>)state;
var taskCompletionSource = asyncState.TaskCompletionSource;
var cancellationToken = asyncState.CancellationToken;
if (cancellationToken.IsCancellationRequested) {
taskCompletionSource.TrySetCanceled (cancellationToken);
return;
}
try {
var value = asyncState.Factory ();
taskCompletionSource.TrySetResult (value);
}
catch (Exception exception) {
taskCompletionSource.TrySetException (exception);
}
}
private sealed class State<T> {
public State (Func<T> factory, CancellationToken cancellationToken) {
CancellationToken = cancellationToken;
TaskCompletionSource = new TaskCompletionSource<T> (factory);
}
public CancellationToken CancellationToken { get; }
public TaskCompletionSource<T> TaskCompletionSource { get; }
public Task<T> Task => TaskCompletionSource.Task;
public Func<T> Factory => (Func<T>)Task.AsyncState;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment