1

我有一个从按钮单击触发的后台异步任务。我有一个IsBusy在任务开始时更新的属性,并且在 finally 块内以说明取消或完成。

目前我的按钮点击事件取消了之前的任务并在重新点击时启动了一个新任务;然而,由于第一个任务的取消可能会在新任务的开始之后徘徊,布尔IsBusy指示器可能会变得不同步。

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

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

另一个想法是在任务被触发时存储它,并且只启动新任务作为第一个任务的延续。这解决了取消问题,但会导致不必要的延迟(尽管是部分延迟)和调用者而不是任务的“合同”。

我最后的想法是创建一个类似于 BusyTokenSource 类的东西,它分发一次性的 BusyTokens,这些 BusyTokens 从线程安全集合中添加/删除。但这似乎有点矫枉过正。

有没有更好/正确/通用的方法来处理这种情况?

编辑:

我最终还是按照上面的最后一个想法写了“BusyToken”类。这样我可以简单地将一个函数包装在 a 中using(BusyTokenSource.GetToken()){},让内部收集并Dispose处理计数和忙碌状态。

4

1 回答 1

2

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

创建一个持有者类:

class BusyStatus { bool IsBusy; }

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

只要确保旧任务不会意外引用新BusyStatus实例即可。

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

于 2012-09-27T20:49:56.830 回答