我有一个从按钮点击触发的后台异步任务。我有一个IsBusy
属性,当任务开始时会更新,并在finally块中更新以考虑取消或完成。
目前我的按钮点击事件会取消上一个任务,并在重新点击时启动一个新任务;但是,由于第一个任务的取消可能会延续到新任务的开始,因此布尔IsBusy
指示符可能会变得不同步。
我的问题是如何处理这种情况。
我当前的解决方案不是直接更新布尔值,而是使用在开始和完成时递增/递减的整数 - IsBusy
属性返回BusyCount > 0
。然而,这需要增加线程安全性,并且不是一个好的解决方案。
另一种想法是在触发任务时存储任务,并仅将新任务作为第一个任务的延续启动。这解决了取消问题,但是对调用者而不是任务施加了不必要的延迟(但不是小数)和“合同”。
我最后的想法是创建一个类似BusyTokenSource类的东西,它可以发布从线程安全集合中添加/删除的一次性BusyTokens ......但这看起来有些过分。
是否有更好/适当/通用的方法来处理这种情况?
修改
我结束了上面的最后一次考虑,写了'BusyToken'课程。这样我就可以简单地将函数包装在using(BusyTokenSource.GetToken()){}
中,让内部集合和Dispose
处理计数和繁忙状态。
答案 0 :(得分:2)
我认为每个任务应该有一个忙状态。不确定你的BusyTokenSource
想法是如何运作的,但听起来有点像它。
创建持有者类:
class BusyStatus { bool IsBusy; }
并为您启动的每个任务提供一个新实例。当您不再对旧任务感兴趣时,只需丢弃旧的BusyStatus并创建一个新实例。旧的Task最终将完成并设置忙碌状态,但是在没有人再使用的旧实例上。
只需确保旧任务不会意外引用新的BusyStatus
实例。
作为一般规则,让每个任务(或线程)在不同的数据结构上工作通常很有用。这是一个有用的一般指导原则。它让您变得简单,并且易于实现安全。