如何取消异步调用?

如何取消异步调用? .NET APM似乎不支持此操作。

我的代码中有以下循环,它在ThreadPool上生成多个线程。 当我单击UI上的按钮时,我希望这些线程(或异步调用)结束。

foreach (var sku in skus) { loadSku.BeginInvoke(... } 

除了创建全局“取消标志”并使用异步方法查找它之外,还有其他优雅的解决方案吗?

“取消标志”是这样做的方式,虽然不是全球性的,但必然。 不可避免的一点是,你需要一些方法向线程发出信号,告诉它应该停止它正在做的事情。

BeginInvoke的情况下,除了全局标志之外,这很难做到,因为工作是在线程池上执行的,而你不知道哪个线程。 您有几个选项(按优先顺序排列):

  1. 使用BackgroundWorker而不是BeginInvoke 。 这具有取消function 。 这还有其他好处,例如进度监控和“工作完成”回调 。 它也很好地处理exception 。
  2. 使用ThreadPool.QueueUserWorkItem ,将对象作为具有Cancel()方法的状态传入,该方法设置执行代码可以检查的Cancelled标志。 当然你需要保持对状态对象的引用,这样你就可以在它上面调用Cancel() (这是BackgroundWorker为你做的事情 – 你的表单上有一个组件。(感谢Fredrik提醒你) 。
  3. 创建自己的ThreadStart委托,与选项2一样传入状态对象。

如果你正在寻找“TerminateAsnyc”方法,你将找不到一个。 因此,不,使用Control.BeginInvoke / EndInvoke时可能没有优雅的方法。 因此,我将布尔标志放在UI线程上,让异步执行的委托在执行时定期检查该标志。

但是,您可能会检查使用后台工作线程。

肯定有其他解决方案,虽然我不知道我会称之为“优雅”。

您可以在线程上调用Abort或Interrupt,但这些可能会产生一些负面影响。 就个人而言,如果可能的话,我更喜欢使用BackgroundWorker。 它有一个Cancelfunction,但它类似于你提到的 – 类中的bool标志,你必须在执行代码中定期检查(至少它不是全局标志)。 关于在.NET中停止线程的这篇文章有点旧,但是我在上面提到的其他选项中遇到了一些陷阱。