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

Threads locked in TraceSource methods by Console

我运行遇到了一个情况,不知道能否解决。

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

出于调试目的,我的服务在控制台 window 中配置为 运行。我知道这与问题有关,因为我也在写信给 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);

    ///...
}

当我 运行 控制台中的服务,并使用 quickedit 模式单击或 select 鼠标在控制台 window 的任意位置时, TraceSource 方法调用锁定启动应用程序的其余部分,直到我按下一个也停止应用程序的键。

有什么方法可以防止此控制台线程锁定其他线程?还是我误解了这里发生的事情?


在我点击控制台 window 重现问题后,调用堆栈可能如下所示:

线程 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#

线程 2

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

OP:

When I run the service in console, and click with the mouse anywhere in the console window, the TraceSource method calls lock up the rest of the application, until I hit a key which also stops the application.

Would you try turning on quickedit in your console, and use the mouse to highlight some characters?

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

要继续执行,请按 Esc 或单击 鼠标右键

OP:

I was wondering do you know if there was a way to prevent this behaviour

是的,吉姆米歇尔写道:

If you want to disable quick edit mode, you need to call GetConsoleMode to get the current mode. Then clear the bit that enables quick edit

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