Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable Task Parallel Library's ETW EventSource in a Universal App?

Task Parallel Library uses 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.

A possible workaround would be to disable the TPL's ETW EventSource.

How do I disable it from within a Universal Windows app, if I really want to?

Reflection works for a Desktop app, but not for a WP/WinRT app. EventCommand.Disable is not recognized as a valid command for EventSource.SendCommand (although it's used internally in ETW). Here's the code to play with (as a console app):

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();
        }
    }
}

For a Universal app, MyEventListener can just be instantiated as part of Application:

public sealed partial class App : Application
{
    static MyEventListener listener = new MyEventListener();
}
like image 899
noseratio Avatar asked Nov 01 '22 10:11

noseratio


1 Answers

I ran into a similar issue and found a potential solution.

You can simply call Dispose() on the EventSource!

This will not remove the event source, but it will disable it. And the base EventSource that they all inherit from does have the proper checks in place to prevent the rest of the inherited class from being called when it is disabled. So, in theory, it should be safe. But there may be some EventSource implementations where this will not work, so test it thoroughly!

See here for the EventSource.Dispose(bool disposing) implementation.

like image 67
TylerOhlsen Avatar answered Nov 09 '22 12:11

TylerOhlsen