如何取消异步通话? .NET APM似乎不支持此操作。
我的代码中有以下循环,它在ThreadPool上生成多个线程。当我单击UI上的按钮时,我希望这些线程(或异步调用)结束。
foreach (var sku in skus)
{
loadSku.BeginInvoke(...
}
除了创建全局“取消标志”并使用异步方法查找它之外,还有其他优雅的解决方案吗?
答案 0 :(得分:18)
“取消标志”是这样做的方式,虽然不是全球性的,但必然。不可避免的一点是,您需要某种方式向线程发出信号,告知它应该停止它正在做的事情。
在BeginInvoke
的情况下,除了全局标志之外,这很难做到,因为工作是在线程池上执行的,而你不知道哪个线程。您有几个选项(按优先顺序排列):
BackgroundWorker
代替BeginInvoke
。这有cancellation functionality baked-in。这还有其他好处,例如progress monitoring和"Work complete" callbacks。它也很好handles exceptions。ThreadPool.QueueUserWorkItem
,将对象作为具有Cancel()
方法的状态传入,该方法设置执行代码可以检查的Cancelled
标志。当然,您需要保留对状态对象的引用,以便可以在其上调用Cancel()
(这是BackgroundWorker
为您所做的事情 - 您的表单上有一个组件。(感谢Fredrik提醒您注意这一点。)ThreadStart
委托,与选项2一样传入州对象。答案 1 :(得分:1)
如果您正在寻找“TerminateAsnyc”方法,则无法找到。因此,不,使用Control.BeginInvoke / EndInvoke时可能没有优雅的方法。因此,我将布尔标志放在UI线程上,让异步执行的委托在执行时定期检查该标志。
但是,您可能会检查使用后台工作线程。
答案 2 :(得分:0)
肯定有其他解决方案,虽然我不知道我会称之为“优雅”。
您可以在线程上调用Abort或Interrupt,但这些可能会产生一些负面影响。就个人而言,如果可能的话,我更喜欢使用BackgroundWorker。它有一个Cancel功能,但它类似于你提到的 - 类中的bool标志,你必须在执行代码中定期检查(至少它不是全局标志)。 This post on stopping threads in .NET有点旧,但是我在上面提到的其他选项中遇到了一些陷阱。