public async Task InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal, CancellationToken ct = default) { ThrowOnInvokeIfStateIsInvalid(); var workItem = new DispatcherItem(action); _queues[(Int32)priority].Enqueue(workItem); _newWorkSemaphore.Release(); var result = await workItem.WaitAsync(ct); if (result is Exception ex) { throw ex; } }
public async Task <TResult> InvokeAsync <TResult>(Func <TResult> func, DispatcherPriority priority = DispatcherPriority.Normal, CancellationToken ct = default) where TResult : class { ThrowOnInvokeIfStateIsInvalid(); var workItem = new DispatcherItem(func); _queues[(Int32)priority].Enqueue(workItem); _newWorkSemaphore.Release(); var result = await workItem.WaitAsync(ct); if (result is Exception ex) { throw ex; } return((TResult)result); }
public void Run() { State = DispatcherState.Running; while (true) { // Wait for new work or dispatcher shutting down _newWorkSemaphore.Wait(); if (State == DispatcherState.ShuttingDown) { foreach (var queue in _queues) { foreach (var item in queue) { item.SignalFinishedWithException(new OperationCanceledException()); } } break; } // Pick highest priority work DispatcherItem dispatcherItem = null; for (Int32 i = _queues.Length - 1; i >= 0; i--) { _queues[i].TryDequeue(out dispatcherItem); if (dispatcherItem != null) { break; } } // This, actually, should never happen if (dispatcherItem == null) { throw new DispatcherException("Work is null"); } // Execute user action try { if (dispatcherItem.DelegateWithoutResult != null) { dispatcherItem.DelegateWithoutResult.Invoke(); dispatcherItem.SignalFinished(); } else { var result = dispatcherItem.DelegateWithResult.Invoke(); dispatcherItem.SignalFinished(result); } } catch (Exception ex) { dispatcherItem.SignalFinishedWithException(ex); } } _shutdownTaskCompletionSource.SetResult(null); }