2011-06-14 22 views
3

我正在調試一個定期引發IOException的測試,注意到一個文件不能被刪除,因爲它正在被另一個進程使用。我懷疑這個過程確實是我的測試工具,並且當我期望的時候,進程中的某個其他線程還沒有處理它的文件資源。哪個調試工具(如果有的話)允許我識別持有文件鎖定的線程?

有沒有一種工具可以用來確定哪個線程持有阻礙鎖?如果我能夠識別線程,那麼我可以檢查它的調用堆棧,並至少嘗試確定資源尚未處理的原因。 SOS debugging tool看起來很有希望,但是我沒有看到任何能夠從我的調查中消除大量猜測的功能。

一個想法是確定本地操作系統線程ID,然後可以通過SOS將其映射到託管線程ID。我將如何完成前者?

回答

2

如果在try{delete();}catch(IOException) catch子句中放置斷點。你不能看看每個線程的調用堆棧嗎?

+0

如果您在VisualStudio的異常捕獲,然後打開「線程」視圖('調試相關部分|視窗| Threads',從主菜單),那麼它應該在當前線程旁邊顯示一個黃色箭頭,該箭頭應該與發生異常的那個線程相同。 – CodingWithSpike 2011-06-14 19:48:53

+0

是的,我可以。我可能不得不訴諸於此,這可能會很費力,因爲當時可能有多個線程正在運行。 – 2011-06-14 20:23:34

+0

我聽說FxCop(在編譯時)可以在代碼中發現一些一次性問題。你有沒有考慮過這個? – 2011-06-14 20:29:42

5

您可以使用SysInternals工具中的Process Explorer。 http://technet.microsoft.com/en-us/sysinternals/bb896653 只需打開它並搜索您的文件名。它會告訴你哪些進程有鎖定。


編輯:

哦,我只是重新閱讀,發現你要的特定線程。我不知道ProcessExplorer是否可以做到這一點。抱歉!


編輯2:

第二個答案,這對代理-J的回答擴展:

如果你可以編輯代碼,並添加一個try/catch圍繞它來獲得IOException異常,您也可以登錄堆棧跟蹤,因爲它聽起來就像是你要檢查什麼:

catch(IOException) 
{ 
    LogMessage(string.Format(
     "Managed Thread Id: {0}", 
     System.Threading.Thread.CurrentThread.ManagedThreadId)); 

    LogMessage(string.Format(
     "Stack Trace: {0}", 
     new System.Diagnostics.StackTrace(true).ToString())); 
} 

編輯3

使用上面的方法,你也可以登錄的進程中的所有線程的線程和堆棧跟蹤,使其更容易通過日誌看看,弄清楚發生了什麼拋屍。更新後的代碼:

catch(IOException) 
{ 
    foreach (var thread in System.Diagnostics.Process.GetCurrentProcess().Threads) 
    { 
    LogMessage(string.Format(
     "Managed Thread Id: {0}", 
     thread.ManagedThreadId)); 

    LogMessage(string.Format(
     "Stack Trace: {0}", 
     new System.Diagnostics.StackTrace(thread, true).ToString())); 

    } 
} 
+0

......如果你將它指向你的符號,你可以看到線程並獲得堆棧跟蹤。 – AntonyW 2011-06-14 19:44:34

+0

感謝您的信息,但是這將隔離捕獲異常的線程的調用堆棧。我感興趣的是確定持有鎖的線程,這通常並不相同。但是,我可能需要訴諸於agent-j的解決方案。 – 2011-06-14 20:29:52

+0

@Steve Guidi - 您也可以使用上述方法爲流程中的所有線程轉儲堆棧跟蹤。我沒有真正測試過,但我認爲它會起作用。看到我上面的最新編輯... – CodingWithSpike 2011-06-15 14:16:53

0

線程對文件沒有鎖定(至少不像操作系統那樣)。考慮下面的例子。線程t創建一個文件並鎖定該文件。主線程寫入流並關閉它。這表明該線程不擁有該鎖。該過程確實如此。

 Stream stream = null; 
    Thread t = new Thread(() => stream = File.OpenWrite (@"c:\temp\junk111.txt")); 
    t.Start(); 
    Thread.Sleep(1000); 
    Console.WriteLine(t.ThreadState); 
    stream.WriteByte(89); 
    stream.Close(); 
    File.OpenWrite (@"c:\temp\junk222.txt"); 

打印stopped,以便打開該文件不運行了,但該文件處理它創建線程仍處於打開狀態。

這裏的FxCop的結果對上述文件

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop>FxCopCmd.exe /file:c:\code\jeremy.sellars\test\Junk\bin\Debug\Junk.exe /console 
Microsoft (R) FxCop Command-Line Tool, Version 10.0 (10.0.30319.1) X86 
Copyright (C) Microsoft Corporation, All Rights Reserved. 

... 
[Location not stored in Pdb] : warning : CA2210 : Microsoft.Design : Sign 'Junk.exe' with a strong name key. 
C:\code\jeremy.sellars\TEST\Junk\Program.cs(50,1) : warning : CA2000 : Microsoft.Reliability : In method 'Program.Main()', call System.IDisposable.Dispose on object 'File.OpenWrite("c:\\temp\\junk2.txt")' before all references to it are out of scope. 
Done:00:00:06.1251568 

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop>