【问题标题】:Which debugging tool (if any) allows me to identify the thread that is holding a lock on a file?哪个调试工具(如果有)允许我识别持有文件锁的线程?
【发布时间】:2011-09-14 23:54:31
【问题描述】:

我正在调试一个定期引发IOException 的测试,注意到一个文件不能被删除,因为它正在被另一个进程使用。我怀疑该进程确实是我的测试工具,并且该进程中的某些其他线程没有按照我的预期处理它的文件资源。

有没有一种工具可以用来确定哪个线程持有阻碍锁?如果我可以识别线程,那么我可以检查它的调用堆栈并至少尝试确定为什么资源还没有被释放。 SOS debugging tool 看起来很有希望,但我没有看到任何可以消除我调查中大量猜测的功能。

一种想法是识别本机操作系统线程 ID,然后可以通过 SOS 将其映射到托管线程 ID。我将如何完成前者?

【问题讨论】:

    标签: .net io ioexception sos file-locking


    【解决方案1】:

    您可以使用 SysInternals 工具中的 Process Explorer。 http://technet.microsoft.com/en-us/sysinternals/bb896653 只需打开它并搜索您的文件名。它会告诉你哪些进程被锁定了。


    编辑:

    哦,我刚刚重读了一遍,发现您要求的是特定线程。我不知道 ProcessExplorer 是否可以做到这一点。对不起!


    编辑 2:

    第二个答案,扩展了 agent-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()));
    
      }
    }
    

    【讨论】:

    • ...如果你把它指向你的符号,你可以看到线程并获得堆栈跟踪。
    • 感谢您的信息,但是这将隔离捕获异常的线程的调用堆栈。我有兴趣识别持有锁的线程,这通常不一样。但是,我可能需要求助于 agent-j 的解决方案。
    • @Steve Guidi - 您也可以使用我上面的方法转储进程中所有线程的堆栈跟踪。我还没有实际测试过,但我认为它会起作用。在上面查看我的最新编辑...
    【解决方案2】:

    如果您在try{delete();}catch(IOException) catch 子句中放置断点。那你就不能看看每个线程的调用栈吗?

    【讨论】:

    • 如果您在 VisualStudio 中处于异常捕获状态,然后打开“线程”视图(主菜单中的Debug | Windows | Threads),那么它应该在当前线程旁边显示一个黄色箭头,它应该是捕获异常的同一个。
    • 是的,我可以。我可能不得不求助于这个,这可能会很费力,因为当时可能有多个线程在运行。
    • 我听说FxCop(在编译时)可以在代码中发现一些一次性问题。你考虑过这个吗?
    【解决方案3】:

    线程不会锁定文件(至少在操作系统方面不会)。考虑以下示例。线程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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 2010-09-08
      相关资源
      最近更新 更多