I am interested in listening to ETW (event tracing for Windows) TPL events, in particular I'd like to know when a
Task starts and when it stops.
Here's a sample program I've used for testing:
class Listener : EventListener
private static readonly Guid tplGuid = new Guid("2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5");
protected override void OnEventSourceCreated(EventSource eventSource)
Console.WriteLine("Got guid: " + eventSource.Guid);
protected override void OnEventWritten(EventWrittenEventArgs eventData)
Console.WriteLine("Event: " + eventData.EventId);
static void Main(string args)
using (var listener = new Listener())
Action doIt = null;
doIt = () =>
Parallel.Invoke(() => Console.WriteLine("invoke"));
Sample output is as follows on my machine:
Got guid: 8e9f5090-2d75-4d03-8a81-e5afbf85daf1
Got guid: 2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5
So the Invoke method causes an event to fire, yet the Tasks fire none. Looking at the Task source (e.g. reference source) the code appears no different from how the
Parallel.Invoke event fires.
What is wrong with the above, or, how do I listen to TaskStarted and TaskCompleted events (or any Task related event for that matter)?
Best How To :
Your question challanged me to look into ETW (which i've been wanting to look into for a while). I was able to capture "task start" and "task end" using Microsoft.Diagnostics.Tracing.TraceEvent NuGet library with the simple following code:
private static void Main(string args)
using (var session = new TraceEventSession("TplCaptureSession"))
"TaskExecute/Start", @event =>
Console.WriteLine("Inside Task Started");
"TaskExecute/Stop", @event =>
Console.WriteLine("Inside Task Stopped");
var task = Task.Run(async () =>
Basically what happens is:
We start new a live event capturing session using
TraceEventSession where we pass it
TraceEventLevel.Always to print out all messages (we could narrow this down to
TranceEventLevel.Information, but for the example i chose all).
We enable the TplEventSource provider by passing its
We register a callback to be invoked once
TplEventSource (which is the event source for TPL, obviously) fires either
TaskExecute/Stop events (taken from the reference source)
We print out once we're inside the event.
Note my use of
Task.Run was simply because
session.Source.Process() is a blocking call, and i wanted it to run in the background.