public void WorkAndSetTcs(Func <CancellationToken, Task <IReadOnlyList <HierarchicalSymbol> > > asyncWork) { CancellationTokenSource currentCts; TaskCompletionSource <IReadOnlyList <HierarchicalSymbol> > currentTcs; lock (_syncObj) { switch (state) { case WorkQueueState.Working: CancelExistingWork(); RenewTcs(); break; case WorkQueueState.WaitingForWork: break; case WorkQueueState.FinishedWork: RenewTcs(); break; default: throw new InvalidOperationException(); } state = WorkQueueState.Working; currentCts = _fileCts; currentTcs = _fileTcs; } DoWork(currentCts, asyncWork).SetCompletionResultTo(currentTcs); }
private async Task <IReadOnlyList <HierarchicalSymbol> > DoWork(CancellationTokenSource tcs, Func <CancellationToken, Task <IReadOnlyList <HierarchicalSymbol> > > asyncWork) { var token = tcs.Token; try { return(await asyncWork(token)); } finally { lock (_syncObj) { tcs.Dispose(); if (!token.IsCancellationRequested) { state = WorkQueueState.FinishedWork; } } } }
public void MarkAsPending() { lock (_syncObj) { switch (state) { case WorkQueueState.WaitingForWork: break; case WorkQueueState.Working: CancelExistingWork(); RenewTcs(); break; case WorkQueueState.FinishedWork: RenewTcs(); break; default: throw new InvalidOperationException(); } state = WorkQueueState.WaitingForWork; } }
public void Dispose() { lock (_syncObj) { switch (state) { case WorkQueueState.Working: CancelExistingWork(); break; case WorkQueueState.WaitingForWork: CancelExistingWork(); // Manually cancel tcs, in case any task is awaiting _fileTcs.TrySetCanceled(); break; case WorkQueueState.FinishedWork: break; default: throw new InvalidOperationException(); } state = WorkQueueState.FinishedWork; } }