控制台在TraceSource方法中锁定线程

时间:2016-02-08 03:21:30

标签: c# .net multithreading deadlock trace

我遇到了一种情况,我不知道它是否可以解决。

我已经开始向我的多线程服务添加TraceSource和trace语句,并且我在代码中处理跟踪方法的线程中遇到了锁。这导致整个应用程序挂起。

我的服务配置为在控制台窗口中运行以进行调试。我知道这与问题有关,因为我也在写ConsoleTraceListener

这种锁定似乎发生在外部代码和对Console.ReadKey()的内部调用之间。作为代码和配置的示例,我的应用程序可以在异步方法中进行这些调用:

class MyService : ServiceBase
{
    static TraceSource trace = new TraceSource("mysource");

    void asyncMethod1()
    {
        trace.TraceInformation("Some useful information.");
    }

    void asyncMethod2()
    {
        trace.TraceInformation("Some other useful information.");
    }

    /// other members and methods ...
}

TraceSourceapp.config文件中定义为

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
  <system.diagnostics>
    <trace autoflush="true" indentsize="4" useGlobalLock="true" />
    <sources>
      <source name="mysource" switchName="TraceSwitch" switchType="System.Diagnostics.SourceSwitch">
        <listeners>
          <add name="console" />
          <add name="eventlog" />
          <add name="logfile" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="console" type="System.Diagnostics.ConsoleTraceListener" initializeData="false" />
      <add name="eventlog" type="System.Diagnostics.EventLogTraceListener" initializeData="EventSource">
        <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error"/>
      </add>
      <add name="logfile" type="System.Diagnostics.TextWriterTraceListener" initializeData="logfiles\errors.log">
        <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error"/>
      </add>
    </sharedListeners>
    <switches>
      <add name="TraceSwitch" value="Information" />
    </switches>
  </system.diagnostics>
</configuration>

重现问题

应用启动后,Program.Main(args[])中的代码会等待Console.ReadKey()停止该应用。

static int Main(string[] args)
{
    /// ...

    MyService service = new MyService();
    service.StartService();

    Console.WriteLine("Press any key to exit application.");
    Console.ReadKey(true);

    ///...
}

当我在控制台中运行服务,并使用快速编辑模式在控制台窗口的任何位置单击或选择鼠标时,TraceSource方法调用会锁定应用程序的其余部分,直到我按下一个也是停止申请。

有没有办法可以阻止此控制台线程锁定其他线程?或者我是否误解了这里发生的事情?

在我单击控制台窗口以重现问题后,调用堆栈可能如下所示:

THREAD 1

[Managed to Native Transition]  
System.IO.__ConsoleStream.WriteFileNative
System.IO.__ConsoleStream.Write
System.IO.StreamWriter.Flush
System.IO.StreamWriter.Write
System.IO.TextWriter.SyncTextWriter.Write
System.Diagnostics.TextWriterTraceListener.Write
System.Diagnostics.TraceListener.WriteHeader
System.Diagnostics.TraceListener.TraceEvent
System.Diagnostics.TraceSource.TraceEvent
System.Diagnostics.TraceSource.TraceInformation
myservice.MyService.asyncMethod1 Line 202   C#

THREAD 2

System.Threading.Monitor.Enter
System.Diagnostics.TraceSource.TraceEvent
System.Diagnostics.TraceSource.TraceInformation
myservice.MyService.asyncMethod2 Line 134   C#

1 个答案:

答案 0 :(得分:3)

OP:

  

当我在控制台中运行服务,并在控制台窗口的任何位置单击鼠标时,TraceSource方法调用锁定应用程序的其余部分,直到我按下一个也停止应用程序的键。

     

您是否尝试在控制台中启用quickedit,并使用鼠标突出显示某些字符?

根据我们在上面的问题下方的对话,它似乎挂起的原因是在 QuickEdit 模式/突出显示文本期间,所有线程都会暂停控制台输出。这已在Visual Studio调试器中得到确认。

要恢复执行,请按 Esc 或点击鼠标右键

OP:

  

我想知道你是否有办法防止这种行为

是的,Jim Mishel写道:

  

如果要禁用快速编辑模式,则需要调用GetConsoleMode以获取当前模式。然后清除启用快速编辑的位

您可以找到有关Jim's answer here的更多信息。