Skip to content

Instantly share code, notes, and snippets.

@DarkOoze
Last active April 11, 2024 06:53
Show Gist options
  • Save DarkOoze/38748365e634c1f70ecb542faf61f8fa to your computer and use it in GitHub Desktop.
Save DarkOoze/38748365e634c1f70ecb542faf61f8fa to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Forms;
public static class TaskExtensions
{
/// <summary>
/// Creates an awaitable task that asynchronously yields back to the current context of the control.
/// </summary>
/// <param name="control"></param>
/// <returns>A context that, when awaited, will asynchronously transition back into the
/// context of the control.</returns>
public static ControlYieldAwaitable Yield(this Control control)
{
return new ControlYieldAwaitable(control);
}
public struct ControlYieldAwaitable
{
private readonly Control control;
public ControlYieldAwaitable(Control control)
{
this.control = control;
}
public YieldAwaiter GetAwaiter()
{
return new YieldAwaiter(this.control);
}
public readonly struct YieldAwaiter : ICriticalNotifyCompletion, INotifyCompletion
{
private readonly SynchronizationContext syncContext;
private static readonly SendOrPostCallback sendOrPostCallbackRunAction = RunAction;
public YieldAwaiter(Control control)
{
this.syncContext = GetSynchronizationContext(control);
}
public bool IsCompleted => this.syncContext == SynchronizationContext.Current;
public void OnCompleted(Action continuation)
{
this.syncContext.Post(sendOrPostCallbackRunAction, continuation);
}
public void UnsafeOnCompleted(Action continuation)
{
this.syncContext.Post(sendOrPostCallbackRunAction, continuation);
}
public void GetResult()
{
}
private static SynchronizationContext GetSynchronizationContext(Control control)
{
if (control.InvokeRequired)
return (SynchronizationContext)control.Invoke(new Func<Control, SynchronizationContext>(GetSynchronizationContext), control);
return SynchronizationContext.Current;
}
private static void RunAction(object state) => ((Action)state).Invoke();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment