异步操作的非协作式取消

3
在我的Windows窗体应用程序中,我需要调用第三方数学库(Accord.NET)的长时间运行操作。在计算过程中,我希望保持GUI的响应性,并且给用户取消长时间运行操作的可能性。
是否有一种方法可以在后台线程中执行该函数并使用户有可能取消它?请注意,我想调用的长时间运行函数位于外部库中,不接受CancellationToken(否则我可以轻松地使用ThreadPool的QueueUserWorkItem等)。因此,我正在寻找一种非协作式取消操作的方法。

为什么不使用托管线程? - Candide
4
唯一安全的方法是在一个单独的 AppDomain 中运行该代码。 - H H
@HenkHolterman:你有如何在单独的AppDomain中执行函数的示例吗?我猜创建和销毁新的AppDomain会涉及相当大的开销? - Robert Hegner
2个回答

3
我认为你有三个选择。
一、将计算分到自己的线程中。这样可以保持UI的响应性。不要提供取消按钮,只需让用户知道一旦启动就无法停止。
二、像上面一样将计算分到自己的线程中;然而,通过简单地降低线程的优先级来“假装”取消它。你可以让计算继续进行,但在主线程中停止报告进度。当完成时,只需丢弃结果。
三、将计算放入自己的appdomain /进程中。如果需要,可以杀死该外部进程。
每种选择都有好坏之处。

1
+1 建议孤立该线程,让它饿死,让它孤独地被忽视而死亡,无人哀悼,无挽歌、无墓志铭(哭泣..) - Martin James
@MartinJames:;) 在这种情况下,我想起了一些旧的Mötley Crüe歌词:“不要生气离开,只是走开就好…” - NotMe

1

什么?只需使用一个线程和一个工作方法。

Thread thread = new Thread(MyWorkerMethod);
thread.Start();

thread.Abort();


void MyWorkerMethod() {
    // do anything you want in here
}

如果他使用了受保护的代码块(例如catch块),那么就不应该有问题。否则,我是否漏掉了什么? - ChrisB
看起来我错过了最明显的解决方案... :) 感谢 @ChrisB 指出这一点。 - Robert Hegner
如果我正确理解Thread.Abort的文档,只要我的工作函数不持有任何锁,并且不调用任何静态构造函数,同时我使用的是.NET 2.0或更高版本,那么使用它应该没有问题。我很确定我想调用的算法不需要任何锁,但是对于静态构造函数,我不太确定... - Robert Hegner
如果你要中止的线程正在运行第三方代码,正如OP所提到的那样,为什么中止它会有影响呢?我读过的所有反对Thread.Abort()的文章都是批评它作为设计的一部分使用,而不是与第三方代码相关。即使是Peter Ritchie的文章也评论道:“如果不是你的代码(即它是你无法控制的代码),那么是的,你别无选择。” - Rich Tebb
第三方代码完全是一个黑洞的情况并不常见。通常,它会调用、打开、读取或执行某些可以发出信号引发异常的操作。这似乎是一个数学库,因此您可以将传递给它的所有数据设置为零,并等待异常出现。 - Martin James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接