Skip to content

Instantly share code, notes, and snippets.

@espresso3389
Created August 8, 2016 08:20
Show Gist options
  • Save espresso3389/795b90dac72d98332505c4dc11e9a68f to your computer and use it in GitHub Desktop.
Save espresso3389/795b90dac72d98332505c4dc11e9a68f to your computer and use it in GitHub Desktop.
A wrapper code to use GCD with C#'s async/await.
using CoreFoundation;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace BackgroundDispatcher
{
/// <summary>
/// Wrapper for Grand Central Dispatch.
/// </summary>
public class BackgroundDispatcher : IDisposable
{
/// <summary>
/// Create a background dispatcher.
/// </summary>
/// <param name="name"></param>
public BackgroundDispatcher(string name)
{
dispatcher = new DispatchQueue(name);
}
/// <summary>
/// Invoke a function on the background dispatcher.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func">Function to invoke.</param>
/// <returns>The return value from the function.</returns>
public async Task<T> InvokeOnDispatcherAsync<T>(Func<T> func)
{
if (dispatcher == null)
throw new TaskCanceledException(); // FIXME: What's appropriate for the problem?
var tcs = new TaskCompletionSource<T>();
dispatcher.DispatchAsync(() => tcs.SetResult(func()));
return await tcs.Task;
}
/// <summary>
/// Invoke an action on the background dispatcher.
/// </summary>
/// <param name="action">Action to invoke.</param>
/// <returns></returns>
public async Task InvokeOnDispatcherAsync(Action action)
{
await InvokeOnDispatcherAsync(() => { action(); return 0; });
}
/// <summary>
/// Invoke a function on the background dispatcher.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func">Function to invoke.</param>
/// <returns>The return value from the function.</returns>
public T InvokeOnDispatcher<T>(Func<T> func)
{
if (dispatcher == null)
throw new TaskCanceledException(); // FIXME: What's appropriate for the problem?
if (IsOnDispatcherThread)
return func();
T ret = default(T);
dispatcher.DispatchSync(() =>
{
ret = func();
});
return ret;
}
public bool IsOnDispatcherThread
{
get
{
return DispatchQueue.CurrentQueue == dispatcher;
}
}
/// <summary>
/// Invoke an action on the background dispatcher.
/// </summary>
/// <param name="action">Action to invoke.</param>
public void InvokeOnDispatcher(Action action)
{
InvokeOnDispatcher<bool>(() => { action(); return true; });
}
DispatchQueue dispatcher;
public void Terminate()
{
if (dispatcher != null)
{
dispatcher.Dispose();
dispatcher = null;
}
}
protected virtual void Dispose(bool disposing)
{
Terminate();
}
~BackgroundDispatcher()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment