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

1

5

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();
}
Ake answered 12/2, 2015 at 8:43 Comment(0)
D
2

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.

Dismount answered 7/11, 2018 at 14:24 Comment(1)
Didn't have a chance to check this for UWP but that seems to be working well for Desktop. Did they add IDispose support for EventListener somewhat recently? I don't remember seeing there 3 yrs ago :)Ake

© 2022 - 2024 — McMap. All rights reserved.