我使用BackgroundWorker
来处理长时间运行的外部操作。但是,用户可以选择取消后台操作。由于我的自定义BackgroundWorker支持Thread.Abort()
,所以当用户从主线程触发取消时,我所做的只是BackgroundWorker.Abort()
。
但该线程实际上并未终止,它仍在完成外部进程。有什么方法可以立即终止一个帖子。
我无法控制外部处理,因此无法为while (checkThreadCancelled){}
等方法发送任何标记。
下面是我的伪代码。
任何帮助?
AbortableBackgroundWorker _bgWorker;
void MainThreadFunc()
{
_bgWorker = new AbortableBackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(bg_DoWork);
_bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
( bg_RunWorkerCompleted );
_bgWorker.WorkerSupportsCancellation = true;
_bgWorker.RunWorkerAsync();
}
void bg_DoWork()
{
//Call external dll function for processing
}
void bg_RunWorkerCompleted()
{
//Process completed code
}
void CancelBgProcess()
{
if(_bgWorker != null)
_bgWorker.Abort();
}
答案 0 :(得分:3)
Abort方法依赖于与之协作的工作线程。最终它会导致CLR抛出一个异常,表明该线程将被中止,线程可以随意处理它。
当你的工作线程在DLL中执行某些操作时,CLR无法控制,因此它没有选择抛出异常。
您可以选择使用Win32 TerminateThread API,但这样做很严重,可能会也可能不会导致您的流程中出现损坏。 TerminateThread实际上不是你应该选择的选项。
由于您无法修改要调用的库,因此您有两个选项。第一种也是最简单的方法,降低后台线程的优先级,并忽略它在取消后继续运行的事实。
第二种是在单独的进程而不是线程中启动后台操作。此时,如果取消操作,您可以终止整个过程。如果你走这条路,你需要选择某种形式的IPC来传达图书馆的输入和输出参数。
在这种情况下, Tasks
和CancellationTokens
最终无法帮助您,因为您最终会在同一个地方:执行不与您合作的库代码以便取消。
答案 1 :(得分:1)
您不想使用Thread.Abort
,通常认为这是不好的做法。在SO上提出的许多问题提供了一些非常好的解释。例如:Timeout Pattern - How bad is Thread.Abort really?
尝试查看Tasks
和CancellationTokens
。请参阅此MSDN文章:http://msdn.microsoft.com/en-us/library/dd997396.aspx
答案 2 :(得分:0)
试试这个:
if (_bgWorker.IsBusy)
{
_bgWorker.WorkerSupportsCancellation = true;
//To cancel the Thread if Closing the Application
//while the Background Thread Worker is Still running on Background.
_bgWorker.CancelAsync();
}
它将停止当前线程进程并取消该线程上正在进行的操作。 可能对你有所帮助