如何取消线程?
对于BackgroundWorker
,可以通过DoWork
的e.Cancel
属性报告取消 – 事件处理程序。
如何使用Thread
对象实现相同的function?
以下是一种完成此方法的示例。
private static bool _runThread; private static object _runThreadLock = new object(); private static void Main(string[] args) { _runThread = true; Thread t = new Thread(() => { Console.WriteLine("Starting thread..."); bool _localRunThread = true; while (_localRunThread) { Console.WriteLine("Working..."); Thread.Sleep(1000); lock (_runThreadLock) { _localRunThread = _runThread; } } Console.WriteLine("Exiting thread..."); }); t.Start(); // wait for any key press, and then exit the app Console.ReadKey(); // tell the thread to stop lock (_runThreadLock) { _runThread = false; } // wait for the thread to finish t.Join(); Console.WriteLine("All done."); }
简而言之; 线程检查bool标志,并在标志为true
继续运行。 我更喜欢这种方法而不是调用Thread.Abort
因为它似乎更好,更清洁。
通常,您通过线程的执行作为对象上的方法的委托来执行此操作,该对象公开Cancel
属性,并且长时间运行的操作定期为tru确定是否退出该属性。
例如
public class MyLongTunningTask { public MyLongRunninTask() {} public volatile bool Cancel {get; set; } public void ExecuteLongRunningTask() { while(!this.Cancel) { // Do something long running. // you may still like to check Cancel periodically and exit gracefully if its true } } }
其他地方:
var longRunning = new MyLongTunningTask(); Thread myThread = new Thread(new ThreadStart(longRunning.ExecuteLongRunningTask)); myThread.Start(); // somewhere else longRunning.Cancel = true;
可以通过以下两种方式之一提前停止阻塞的线程:
-
了Thread.interrupt
-
Thread.Abort的
主要问题是,如果线程适用于需要正确释放的任何ressource – 在这种情况下 – 您需要使用运行该线程的实际对象的属性。
有Thread.Abort
,它通过将ThreadAbortException
注入线程来工作。 这有点冒险,因为:
- 如果当时正在执行本机代码,您的线程可能会卡住
- 线程中的代码最好是exception安全的,因为这个
ThreadAbortException
可能发生在它内部的任何代码行上,甚至像i = i + 1
那样无辜的东西
你最好在GUI线程和后台线程之间编写自己的信号机制。 很难在不知道该线程内部发生什么的情况下推荐一些东西,但是我有一个通过等待循环中的某个对象工作的线程,我使用AutoResetEvent
并等待它。