我遇到了一种情况,我不知道它是否可以解决。
我已经开始向我的多线程服务添加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 ...
}
TraceSource
在app.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#
答案 0 :(得分:3)
OP:
当我在控制台中运行服务,并在控制台窗口的任何位置单击鼠标时,TraceSource方法调用锁定应用程序的其余部分,直到我按下一个也停止应用程序的键。
您是否尝试在控制台中启用quickedit,并使用鼠标突出显示某些字符?
根据我们在上面的问题下方的对话,它似乎挂起的原因是在 QuickEdit 模式/突出显示文本期间,所有线程都会暂停控制台输出。这已在Visual Studio调试器中得到确认。
要恢复执行,请按 Esc 或点击鼠标右键。
OP:
我想知道你是否有办法防止这种行为
是的,Jim Mishel写道:
如果要禁用快速编辑模式,则需要调用GetConsoleMode以获取当前模式。然后清除启用快速编辑的位
您可以找到有关Jim's answer here的更多信息。