C# 如何取消一个线程?
在的情况下,可以通过C# 如何取消一个线程?,c#,multithreading,C#,Multithreading,在的情况下,可以通过DoWork-事件处理程序的e.cancel-属性报告取消 如何在对象上实现同样的效果?通常,线程的执行是对象上方法的委托,该对象公开一个Cancel属性,长时间运行的操作会定期检查该属性以确定是否退出 比如说 public class MyLongTunningTask { public MyLongRunninTask() {} public volatile bool Cancel {get; set; } public void ExecuteLo
DoWork
-事件处理程序的e.cancel
-属性报告取消
如何在对象上实现同样的效果?通常,线程的执行是对象上方法的委托,该对象公开一个
Cancel
属性,长时间运行的操作会定期检查该属性以确定是否退出
比如说
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.Abort
,它通过向线程中注入ThreadAbortException
来工作。这有点冒险,因为:
ThreadAbortException
可能发生在其中的任何代码行上,甚至是像i=i+1
最好在GUI线程和后台线程之间编写自己的信令机制。在不知道线程内部发生了什么的情况下,很难推荐一些东西,但是当我有一个线程通过在循环中等待某个对象来工作时,我会使用一个
自动resetevent
,然后再等待它。这里是一个完整的例子,说明了一种方法
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
时保持运行。与调用线程相比,我更喜欢这种方法。Abort
因为它看起来更好更干净。您需要在Cancel成员上添加volatile,以指示它将从另一个线程更改。很好。如果线程使用“try…”,释放资源不一定是个问题。。。最后,“使用”和/或“使用”每个人都反对中断和中止,所以不要使用它们。很好,不过如果您可以根据WaitHandle
而不是轮询来编写代码会更好。当然,这取决于线程中的代码如何工作。@Tim:是的,WaitHandle可能是一种更干净的方法,而不是像我的示例中那样依赖于共享字段。这也将消除锁定的需要,使代码更切中要害。我不愿意将.NET framework的某些部分(如Thread.Abort
方法)完全错误地调用;我只是在脑海中列出了一些需要避免的技巧。