今天,發現我們的一個Windows Service無法正常停止,無奈之下只能殺了進程。 為了找到原因,我在本地進行調試,發現程序裡用到了多線程,而代碼正是卡在了workThread.Abort()語句而無法停止。 為什麼不能Abort? 繼續看線程調用的方法的代碼,發現沒有什麼特殊的代碼,只是在其中用了Thread.Sleep進行長時間等待。 難道是這個引起的? 寫了一個測試程序驗證,
class Program
{
private readonly Thread workThread;
public Program()
{
workThread = new Thread(DoWork);
}
static void Main(string[] args)
{
new Program().Work();
Console.ReadLine();
}
private void Work()
{
workThread.Start();
Thread.Sleep(1 * 1000);
Console.WriteLine("aborting");
workThread.Abort();
Console.WriteLine("aborted");
}
private void DoWork()
{
Console.WriteLine("started");
Thread.Sleep(300 * 1000);
}
}
發現可以正常終止。
started
aborting
aborted
再仔細檢查,發現其中一處Thread.Sleep放在了finally塊中,修改測試代碼
class Program
{
private readonly Thread workThread;
public Program()
{
workThread = new Thread(DoWork);
}
static void Main(string[] args)
{
new Program().Work();
Console.ReadLine();
}
private void Work()
{
workThread.Start();
Thread.Sleep(1 * 1000);
Console.WriteLine("aborting");
workThread.Abort();
Console.WriteLine("aborted");
}
private void DoWork()
{
try
{
Console.WriteLine("started");
}
catch (Exception)
{
throw;
}
finally
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("ThreadState:" + workThread.ThreadState);
Thread.Sleep(1000);
}
}
}
}
輸出: started ThreadState:Running aborting ThreadState:AbortRequested ThreadState:AbortRequested aborted MSDN是這樣解釋的: 線程不一定會立即中止,或者根本不中止。 如果線程在作為中止過程的一部分被調用的 finally 塊中做非常大量的計算,從而無限期延遲中止操作,則會發生這種情況。 http://msdn.microsoft.com/zh-cn/library/5b50fdsz.aspx 其實追根溯源,問題是出在程序員對try-catch-finally的濫用上,finally塊應該是用來做一些收尾工作,而不是等待操作。 finally 塊用於清除 try 塊中分配的任何資源,以及運行任何即使在發生異常時也必須執行的代碼。 http://msdn.microsoft.com/zh-cn/library/zwc8s4fz%28v=vs.80%29.aspx 找到了原因,解決方案也挺簡單,將Thread.Sleep從finally塊中移除即可。