Tag: cancellation

Async / Await等同于.ContinueWith和CancellationToken以及TaskScheduler.FromCurrentSynchronizationContext()调度程序

这是这个问题的后续行动。 问题 :使用async / await而不是.ContinueWith()来表达以下内容的简洁方法是什么?: var task = Task.Run(() => LongRunningAndMightThrow()); m_cts = new CancellationTokenSource(); CancellationToken ct = m_cts.Token; var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task updateUITask = task.ContinueWith(t => UpdateUI(t), ct, TaskContinuationOptions.None, uiTaskScheduler); 我主要对UI SynchronizationContext的情况感兴趣(例如对于Winforms) 请注意,该行为具有以下所有期望的行为: 当CancellationToken被取消时, updateUITask最终会被取消(即LongRunningAndMightThrow工作可能仍会持续很长时间)。 在运行UpdateUI lambda之前, 在UI线程上检查ct CancellationToken是否取消(请参阅此答案 )。 在task完成或出现故障的某些情况下, updateUITask最终会被取消(因为在执行UpdateUI lambda之前在UI线程上检查了ct CancellationToken。 在UI线程上检查CancellationToken和UpdateUI lambda的运行之间没有中断。 也就是说,如果只在UI线程上取消了CancellationTokenSource ,那么在检查CancellationToken和运行UpdateUI lambda之间没有竞争条件 – 没有什么可以在这两个事件之间触发CancellationToken ,因为UI线程在这两个事件之间没有放弃。 讨论: […]

如何在BlockingCollection上取消GetConsumingEnumerable()

在下面的代码中,我使用CancellationToken在生产者没有生成时唤醒GetConsumingEnumerable(),我想要脱离foreach并退出Task。 但我没有看到IsCancellationRequested被记录,我的Task.Wait(timeOut)等待整个timeOut期间。 我究竟做错了什么? userToken.Task = Task.Factory.StartNew(state => { userToken.CancelToken = new CancellationTokenSource(); foreach (var broadcast in userToken.BroadcastQueue.GetConsumingEnumerable(userToken.CancelToken.Token)) { if (userToken.CancelToken.IsCancellationRequested) { Log.Write(“BroadcastQueue IsCancellationRequested”); break; … } } return 0; }, “TaskSubscribe”, TaskCreationOptions.LongRunning); 后来… UserToken.CancelToken.Cancel(); try { task.Wait(timeOut); } catch (AggregateException ar) { Log.Write(“AggregateException ” + ar.InnerException, MsgType.InfoMsg); } catch (OperationCanceledException) { Log.Write(“BroadcastQueue Cancelled”, MsgType.InfoMsg); }