非立即任务取消,重启和繁忙指标

时间:2012-09-27 17:33:56

标签: .net wpf task-parallel-library async-await cancellation

我有一个从按钮点击触发的后台异步任务。我有一个IsBusy属性,当任务开始时会更新,并在finally块中更新以考虑取消或完成。

目前我的按钮点击事件会取消上一个任务,并在重新点击时启动一个新任务;但是,由于第一个任务的取消可能会延续到新任务的开始,因此布尔IsBusy指示符可能会变得不同步。

我的问题是如何处理这种情况。

我当前的解决方案不是直接更新布尔值,而是使用在开始和完成时递增/递减的整数 - IsBusy属性返回BusyCount > 0。然而,这需要增加线程安全性,并且不是一个好的解决方案。

另一种想法是在触发任务时存储任务,并仅将新任务作为第一个任务的延续启动。这解决了取消问题,但是对调用者而不是任务施加了不必要的延迟(但不是小数)和“合同”。

我最后的想法是创建一个类似BusyTokenSource类的东西,它可以发布从线程安全集合中添加/删除的一次性BusyTokens ......但这看起来有些过分。

是否有更好/适当/通用的方法来处理这种情况?

修改

我结束了上面的最后一次考虑,写了'BusyToken'课程。这样我就可以简单地将函数包装在using(BusyTokenSource.GetToken()){}中,让内部集合和Dispose处理计数和繁忙状态。

1 个答案:

答案 0 :(得分:2)

我认为每个任务应该有一个忙状态。不确定你的BusyTokenSource想法是如何运作的,但听起来有点像它。

创建持有者类:

class BusyStatus { bool IsBusy; }

并为您启动的每个任务提供一个新实例。当您不再对旧任务感兴趣时,只需丢弃旧的BusyStatus并创建一个新实例。旧的Task最终将完成并设置忙碌状态,但是在没有人再使用的旧实例上。

只需确保旧任务不会意外引用新的BusyStatus实例。

作为一般规则,让每个任务(或线程)在不同的数据结构上工作通常很有用。这是一个有用的一般指导原则。它让您变得简单,并且易于实现安全。