如何在通用应用程序中禁用任务并行库的 ETW 事件源?
How to disable Task Parallel Library's ETW EventSource in a Universal App?
任务并行库使用 Event Tracing for Windows (ETW) for logging. Apparently, there is a bug related to logging, in either TPL or ETW, surfacing under Windows Phone or Windows Store .NET Runtime. The original issue is described here。
一种可能的解决方法是禁用 TPL 的 ETW EventSource
。
如果我真的想要,如何从通用 Windows 应用程序 中禁用它?
反射适用于桌面应用程序,但不适用于 WP/WinRT 应用程序。 EventCommand.Disable
未被识别为 EventSource.SendCommand
的有效命令(尽管它在 ETW 内部使用)。这是要使用的代码(作为控制台应用程序):
using System;
using System.Threading.Tasks;
using System.Diagnostics.Tracing;
using System.Reflection;
namespace ConsoleApplication
{
class Program
{
internal class MyEventListener : EventListener
{
protected override void OnEventSourceCreated(EventSource eventSource)
{
Console.WriteLine(eventSource);
base.OnEventSourceCreated(eventSource);
if (eventSource.Name == "System.Threading.Tasks.TplEventSource")
{
Console.WriteLine("enabled: " + eventSource.IsEnabled());
// trying to disable with EventCommand.Disable: Invalid command
try
{
System.Diagnostics.Tracing.EventSource.SendCommand(
eventSource, EventCommand.Disable,
new System.Collections.Generic.Dictionary<string, string>());
Console.WriteLine("enabled: " + eventSource.IsEnabled());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// reflection: doesn't work for Windows Phone/Store apps
try
{
var ti = typeof(EventSource).GetTypeInfo();
var f = ti.GetDeclaredField("m_eventSourceEnabled");
f.SetValue(eventSource, false);
Console.WriteLine("enabled: " + eventSource.IsEnabled());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
Console.WriteLine(eventData);
}
}
static MyEventListener listener = new MyEventListener();
static void Main(string[] args)
{
Task.Delay(1000).Wait();
Console.ReadLine();
}
}
}
对于通用应用程序,MyEventListener
可以作为 Application
的一部分进行实例化:
public sealed partial class App : Application
{
static MyEventListener listener = new MyEventListener();
}
我 运行 遇到了类似的问题并找到了可能的解决方案。
您只需在 EventSource 上调用 Dispose()
!
这不会删除事件源,但会禁用它。它们都继承自的基本 EventSource 确实进行了适当的检查,以防止在禁用时调用其余继承的 class。所以,理论上,它应该是安全的。但可能有一些 EventSource 实现不起作用,因此请彻底测试!
有关 EventSource.Dispose(bool disposing)
实施,请参阅 here。
任务并行库使用 Event Tracing for Windows (ETW) for logging. Apparently, there is a bug related to logging, in either TPL or ETW, surfacing under Windows Phone or Windows Store .NET Runtime. The original issue is described here。
一种可能的解决方法是禁用 TPL 的 ETW EventSource
。
如果我真的想要,如何从通用 Windows 应用程序 中禁用它?
反射适用于桌面应用程序,但不适用于 WP/WinRT 应用程序。 EventCommand.Disable
未被识别为 EventSource.SendCommand
的有效命令(尽管它在 ETW 内部使用)。这是要使用的代码(作为控制台应用程序):
using System;
using System.Threading.Tasks;
using System.Diagnostics.Tracing;
using System.Reflection;
namespace ConsoleApplication
{
class Program
{
internal class MyEventListener : EventListener
{
protected override void OnEventSourceCreated(EventSource eventSource)
{
Console.WriteLine(eventSource);
base.OnEventSourceCreated(eventSource);
if (eventSource.Name == "System.Threading.Tasks.TplEventSource")
{
Console.WriteLine("enabled: " + eventSource.IsEnabled());
// trying to disable with EventCommand.Disable: Invalid command
try
{
System.Diagnostics.Tracing.EventSource.SendCommand(
eventSource, EventCommand.Disable,
new System.Collections.Generic.Dictionary<string, string>());
Console.WriteLine("enabled: " + eventSource.IsEnabled());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// reflection: doesn't work for Windows Phone/Store apps
try
{
var ti = typeof(EventSource).GetTypeInfo();
var f = ti.GetDeclaredField("m_eventSourceEnabled");
f.SetValue(eventSource, false);
Console.WriteLine("enabled: " + eventSource.IsEnabled());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
Console.WriteLine(eventData);
}
}
static MyEventListener listener = new MyEventListener();
static void Main(string[] args)
{
Task.Delay(1000).Wait();
Console.ReadLine();
}
}
}
对于通用应用程序,MyEventListener
可以作为 Application
的一部分进行实例化:
public sealed partial class App : Application
{
static MyEventListener listener = new MyEventListener();
}
我 运行 遇到了类似的问题并找到了可能的解决方案。
您只需在 EventSource 上调用 Dispose()
!
这不会删除事件源,但会禁用它。它们都继承自的基本 EventSource 确实进行了适当的检查,以防止在禁用时调用其余继承的 class。所以,理论上,它应该是安全的。但可能有一些 EventSource 实现不起作用,因此请彻底测试!
有关 EventSource.Dispose(bool disposing)
实施,请参阅 here。