Skip to content

Instantly share code, notes, and snippets.

@jnm2
Last active July 20, 2023 21:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jnm2/5638603bc1f5d870c153d359eebaa5e7 to your computer and use it in GitHub Desktop.
Save jnm2/5638603bc1f5d870c153d359eebaa5e7 to your computer and use it in GitHub Desktop.
using System;
using System.Threading;
internal sealed class DeferredAction
{
private static readonly Action SentinelNextSetShouldPost = () => { };
private readonly SynchronizationContext synchronizationContext;
private Action scheduledAction = SentinelNextSetShouldPost;
public DeferredAction()
{
synchronizationContext = SynchronizationContext.Current
?? throw new InvalidOperationException($"{nameof(DeferredAction)} requires a current synchronization context.");
}
public void Set(Action action)
{
var previouslyScheduledAction = Interlocked.Exchange(ref scheduledAction, action);
if (ReferenceEquals(previouslyScheduledAction, SentinelNextSetShouldPost))
synchronizationContext.Post(OnSynchronizationContextPost, state: this);
}
public void Clear() => Set(null);
private static void OnSynchronizationContextPost(object state)
{
var @this = (DeferredAction)state;
Interlocked.Exchange(ref @this.scheduledAction, SentinelNextSetShouldPost)?.Invoke();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment