c# Thread.Abort()和Thread.ResetAbort()的使用
Thread類的Abort()方法用於終止正在運行的線程(.net core中Abort()方法雖然存在,但是調用它會引發PlatformNotSupportedException的異常提示)。它可以強行終止線程,而不管線程是否是sleep中。
執行了Abort()後,被終止的線程就會繼續運行catch{}finally{}塊中代碼,因爲是強行終止,catch塊之後的語句則不再運行。除非在catch語句中執行Thread.ResetAbort()這個靜態方法。
先舉例沒有ResetAbort()的情況:
using System;
using System.Threading;
class Test
{
public static void Main()
{
Thread newThread = new Thread(new ThreadStart(TestMethod));
newThread.Start();
Thread.Sleep(1000);
// Abort newThread.
Console.WriteLine("Main aborting new thread.");
newThread.Abort("Information from Main.");
// Wait for the thread to terminate.
newThread.Join();
Console.WriteLine("New thread terminated - Main exiting.");
}
static void TestMethod()
{
try
{
while (true)
{
Console.WriteLine("New thread running.");
Thread.Sleep(1000);
}
}
catch (ThreadAbortException abortException)
{
Console.WriteLine((string)abortException.ExceptionState);
}
finally
{
Console.WriteLine("Do somthing else in funally{}.");
}
Console.WriteLine("Do somthing else here.");
}
}
/*輸出結果:
New thread running.
Main aborting new thread.
Information from Main.
Do somthing else in funally{}.
New thread terminated - Main exiting.
*/
看輸出結果,可以看到線程被Abort之後,執行catch和finally塊中的內容,但是不會執行finally塊之後的內容。
再看增加ResetAbort()的代碼:
using System;
using System.Threading;
class Test
{
public static void Main()
{
Thread newThread = new Thread(new ThreadStart(TestMethod));
newThread.Start();
Thread.Sleep(1000);
// Abort newThread.
Console.WriteLine("Main aborting new thread.");
newThread.Abort("Information from Main.");
// Wait for the thread to terminate.
newThread.Join();
Console.WriteLine("New thread terminated - Main exiting.");
}
static void TestMethod()
{
try
{
while (true)
{
Console.WriteLine("New thread running.");
Thread.Sleep(1000);
}
}
catch (ThreadAbortException abortException)
{
Console.WriteLine((string)abortException.ExceptionState);
Thread.ResetAbort();
}
finally
{
Console.WriteLine("Do somthing else in funally{}.");
}
Console.WriteLine("Do somthing else here.");
}
}
/*輸出結果:
New thread running.
Main aborting new thread.
Information from Main.
Do somthing else in funally{}.
Do somthing else here.
New thread terminated - Main exiting.
*/
從結果中可以看到,線程被終止了,由於執行了Thread.ResetAbort(),因此就允許繼續執行finally塊之後的代碼。
注意: 如果Thread.ResetAbort()語句放在catch塊中,最好應當把Thread.ResetAbort()語句放在catch{}代碼塊最後,否則會把abortException.ExceptionState中的內容給清空了。Thread.ResetAbort()還可以放在finally塊中,它同樣也可以允許繼續執行finally塊之後的代碼。另外,Thread.ResetAbort()只能執行一次,不能執行二次及以上,否則會出新的異常。
現在解釋一下,在默認(不調用Thread.ResetAbort())的情況下, finally塊後的代碼是執行不到的,這是由於 ThreadAbortException這個異常非常特殊,它會在finally塊的最後(如果沒有finally塊,則是在catch塊的最後)重新扔出一個 ThreadAbortException異常。(不過這個異常在外部抓不到,它僅僅是爲了退出線程用的)。