我创建了一个线程来处理我的代码中的阻塞方法。这样,除了运行该阻塞方法之外,我的代码还可以做其他事情。
问题:如何正确终止线程?我是否必须解除阻塞方法,然后终止线程。还是我可以终止线程而不用担心任何丑陋的崩溃?
我创建了一个线程来处理我的代码中的阻塞方法。这样,除了运行该阻塞方法之外,我的代码还可以做其他事情。
问题:如何正确终止线程?我是否必须解除阻塞方法,然后终止线程。还是我可以终止线程而不用担心任何丑陋的崩溃?
好的,找到了我的答案。我必须声明线程,以便可以对它们进行引用。然后,我首先结束嵌套线程(具有 HandleClientComm()),然后关闭 TCP_Client(如果不为空)和 TCP_Listener。然后我结束 ListenThread()。此外,这里提到的 TCP_Listener.Pending() 方法必须实现停止 TcpListener 的正确方法。
你有一些选择。如果您不关心应用程序关闭时操作是否完成,您最好通过QueueUserWorkItem使用 ThreadPool 线程, 或者(如 Servy 在评论中建议的那样)将线程的IsBackground属性设置为 true,这将允许该过程在线程不退出的情况下退出。
如果您确实关心操作的完成和/或需要在关闭时运行的清理逻辑,那么您可能并不真的想使用 Thread.Abort,至少不是作为您的 goto 策略。我使用的是与此类似的东西:
public abstract class DisposableThread : IDisposable
{
private ManualResetEvent exiting = new ManualResetEvent(false);
private Thread theThread;
private TimeSpan abortTimeout;
public DisposableThread():
this(TimeSpan.FromMilliseconds(100))
{
}
public DisposableThread(TimeSpan abortTimeout)
{
this.abortTimeout = abortTimeout;
theThread = new Thread((_) => ThreadProc());
}
protected virtual void ThreadProc()
{
while(!exiting.WaitOne(0))
{
WorkUnit(exiting);
}
ThreadCleanup();
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
exiting.Set();
if (!theThread.Join(abortTimeout))
{
// logme -- the thread didn't shutdown gracefully
theThread.Abort();
while (!theThread.Join(1000))
{
// logme -- the thread is doing something dumb in an exception handler
}
}
exiting.Dispose();
}
// WorkUnit should return as quickly as safe if the exiting handle is set
// If it doesn't the thread will be aborted if it takes longer than abortTimeout
protected abstract void WorkUnit(WaitHandle exiting);
// override if you need to cleanup on exit
protected virtual void ThreadCleanup() { }
}
这使您的线程有机会优雅地退出,并且只有在优雅退出失败时才会中止。
打电话yourthread.Abort()
。这不像在过去,当资源和锁没有被释放时,这会导致你破坏一切,现在这会引发一个非常好的异常,可以用正常的方式处理......
http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx
当我说“正常方式”时,似乎线程中止异常自动重新引发(相当不错的技巧)
http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx
但这并不能阻止你成为一个混蛋并在接球区开始另一件大事......