全部,这里是一个有关在C#中取消Task:s的复杂情况的设计/最佳实践的问题。你如何实现取消共享任务?如何在C#中实现取消共享任务:s#
作为一个简单的例子,我们假设如下;我们有一个长时间运行,合作可撤销的操作'工作'。它接受一个取消令牌作为参数,并在它被取消时抛出。它在某个应用程序状态下运行并返回一个值。其结果是两个UI组件独立需要的。
当应用程序状态不变,工作函数的值应该被缓存,如果一个计算正在进行,新的请求不应该启动第二个计算,而是开始等待结果。
UI组件的任应能抵消它的任务,而不会影响其他UI组件的任务。
到目前为止你还在我身边吗?
以上可以通过引入包裹在TaskCompletionSources实际工作任务,其任务一个任务的高速缓存来完成:■然后返回到UI组件。如果一个UI组件取消它的任务,它只会放弃TaskCompletionSource任务而不是基础任务。这很好。用户界面组件创建CancellationSource,取消请求是一个正常的自顶向下设计,配合TaskCompletionSource Task在底部。
现在,真正的问题。应用程序状态更改时该怎么办?让我们假设让'工作'功能在状态副本上运行是不可行的。
一个解决办法是听在任务缓存中的状态变化(或有大约)。如果高速缓存具有底层任务使用的CancellationToken,即运行Work功能的任务,则可以取消它。这可能会触发取消所有附加的TaskCompletionSources Task:s,因此这两个UI组件都将获取取消任务。这是一种自下而上的取消。
有没有一种首选的方法来做到这一点?是否有设计模式将其描述在某个地方?
自下而上的取消可以实现,但觉得有点不可思议。 UI任务使用CancellationToken创建,但由于另一个(内部)CancellationToken而被取消。另外,由于令牌不相同,OperationCancelledException不能仅仅在UI中被忽略 - 这将(最终)导致在外部Task:s终结器中引发异常。
非常好的问题,虽然我的第一反应是 “文艺青年最爱的” – dtb
所以,澄清;您有两个消费者的任务结果,并且您只需要一个任务来计算每个应用程序状态的值;但是你希望每个消费者能够“取消”等待任务结果? – Tejs
是的,但是状态的改变也应该取消计算。 – 4ZM