Skip to content

Instantly share code, notes, and snippets.

@MysteryDash
Created August 29, 2018 23:05
Show Gist options
  • Save MysteryDash/bc2e48ca1a0f28fa211ad84a98da2f5c to your computer and use it in GitHub Desktop.
Save MysteryDash/bc2e48ca1a0f28fa211ad84a98da2f5c to your computer and use it in GitHub Desktop.
Provides the caller with means to remove and restore the current SynchronizationContext in an async method.
using System;
using System.Runtime.CompilerServices;
using System.Threading;
/// <summary>
/// Provides the caller with means to remove and restore the current <see cref="SynchronizationContext"/> in an async method.
/// </summary>
public class SynchronizationContextRemover : INotifyCompletion
{
private SynchronizationContextRemover()
{
}
/// <summary>
/// An awaitable <see cref="SynchronizationContext"/> remover.
/// The current <see cref="SynchronizationContext"/> will be restored at the end of the caller's execution.
/// </summary>
public static SynchronizationContextRemover AwaitableRemover => new SynchronizationContextRemover();
/// <summary>
/// A disposable <see cref="SynchronizationContext"/> remover, meant to be used with the <see langword="using"/> statement.
/// The current <see cref="SynchronizationContext"/> will be restored upon disposal of this instance.
/// </summary>
public static IDisposable DisposableRemover => new DisposableContextRemover();
public bool IsCompleted => SynchronizationContext.Current == null;
public void OnCompleted(Action continuation)
{
var previousContext = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
continuation();
}
finally
{
SynchronizationContext.SetSynchronizationContext(previousContext);
}
}
public SynchronizationContextRemover GetAwaiter()
{
return this;
}
public void GetResult()
{
}
private class DisposableContextRemover : IDisposable
{
private readonly SynchronizationContext _previousContext;
internal DisposableContextRemover()
{
_previousContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
}
public void Dispose()
{
SynchronizationContext.SetSynchronizationContext(_previousContext);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment