Created
August 8, 2016 08:20
-
-
Save espresso3389/795b90dac72d98332505c4dc11e9a68f to your computer and use it in GitHub Desktop.
A wrapper code to use GCD with C#'s async/await.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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