private void OnTimerExecute(object context) { // this list must never change or be made public // if that ever changes, then we'll need to make an object used for locks. lock (mTimerQueueData) { // loop through the list and find the timers data that all need to fire now // schedule them in order for (int i = mTimerQueueData.Count - 1; i >= 0; --i) { TimerQueueData data = mTimerQueueData[i]; DateTime now = DateTime.Now; if (data.TargetTime <= now) { mDispatchQueue.DispatchAsync(data.Context, data.Work); mTimerQueueData.RemoveAt(i); } else { mTimer.Change(data.TargetTime - now, Timeout.InfiniteTimeSpan); break; } } } }
public static void DispatchSync(this IDispatchQueue queue, object?context, WaitCallback?work) { TaskCompletionSource <object?> tcs = new TaskCompletionSource <object?>(); queue.DispatchAsync(context, (context) => { work?.Invoke(context); tcs.SetResult(null); }); tcs.Task.Wait(); }
/// <summary>A wrapper over DispatchAsync that calls a value-producing function on the queue and returns it's result via a Task</summary> /// <remarks>Note: the task "completes" on the dispatch queue, so if you use ConfigureAwait(false) or /// TaskContinuationOptions.ExecuteSychronously, you will still be running on the dispatch queue</remarks> /// <typeparam name="T">Result type</typeparam> /// <param name="queue">The queue to execute the function on</param> /// <param name="func">The function to execute</param> /// <returns>A task wrapping the return value (or exception) the func produced.</returns> public static Task <T> DispatchAsync <T>(this IDispatchQueue queue, Func <T> func) { var tcs = new TaskCompletionSource <T>(); queue.DispatchAsync(() => { try { tcs.SetResult(func()); } catch (Exception e) { tcs.TrySetException(e); } }); return(tcs.Task); }