我如何收听TPL TaskStarted / TaskCompleted ETW事件
我有兴趣听ETW(Windows事件跟踪)TPL事件,特别是我想知道Task
何时开始以及何时停止。
以下是我用于测试的示例程序:
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication10
{
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);
EnableEvents(eventSource, EventLevel.LogAlways);
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
Console.WriteLine("Event: " + eventData.EventId);
}
}
class Program
{
static void Main(string[] args)
{
using (var listener = new Listener())
{
Action doIt = null;
doIt = () =>
{
Thread.Sleep(1000);
Console.Write('.');
Task.Run(doIt);
};
Task.Run(doIt);
Parallel.Invoke(() => Console.WriteLine("invoke"));
Console.Read();
}
}
}
}
我的机器上的输出示例如下所示:
Got guid: 8e9f5090-2d75-4d03-8a81-e5afbf85daf1
Got guid: 2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5
Event: 3
invoke
Event: 4
.......
所以Invoke方法会导致一个事件触发,但Tasks不会触发任何事件。 查看任务源(例如参考源),代码与Parallel.Invoke
事件触发方式没有什么不同。
上述有什么问题,或者,我如何收听TaskStarted和TaskCompleted事件(或任何与此有关的任务相关事件)?
你的问题挑起了我对ETW的看法(我一直想进行一番研究)。 我能够使用Microsoft.Diagnostics.Tracing.TraceEvent NuGet库捕获“任务开始”和“任务结束”,其中包含以下简单代码:
private static void Main(string[] args)
{
Task.Run(() =>
{
using (var session = new TraceEventSession("TplCaptureSession"))
{
session.EnableProvider(new Guid("2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5"),
TraceEventLevel.Always);
session.Source.Dynamic.AddCallbackForProviderEvent("System.Threading.Tasks
.TplEventSource",
"TaskExecute/Start", @event =>
{
Console.WriteLine("Inside Task Started");
});
session.Source.Dynamic.AddCallbackForProviderEvent("System.Threading.Tasks
.TplEventSource",
"TaskExecute/Stop", @event =>
{
Console.WriteLine("Inside Task Stopped");
});
session.Source.Process();
}
});
var task = Task.Run(async () =>
{
await Task.Delay(20000);
});
task.Wait();
}
基本上会发生什么是:
我们使用TraceEventSession
开始一个新的实时事件捕获会话,我们通过它TraceEventLevel.Always
打印出所有的消息(我们可以将其缩小到TranceEventLevel.Information
,但对于我选择的所有例子)。
我们通过将其Guid
传递给session.EnableProvider
来启用TplEventSource提供程序。
我们注册一个回调,一旦TplEventSource
(TPL的事件源,显然)触发TaskExecute/Start
或TaskExecute/Stop
事件(从参考源获取)
我们一旦进入活动就打印出来。
注意我对Task.Run
使用很简单,因为session.Source.Process()
是一个阻塞调用,我希望它在后台运行。
以下是我编写的仅使用BCL监听TPL ETW事件的代码示例。
绊倒我的部分是你需要运行这个代码的事实:
// Cause the type initializer for System.Threading.Tasks.TplEtwProvider to run.
// Otherwise async method builders starting events will be missed.
Type.GetType("System.Threading.Tasks.TplEtwProvider, mscorlib", true).GetField("Log").GetValue(null);
否则,一切似乎都按照你期望的方式工作。 不需要第三方库!
链接地址: http://www.djcxy.com/p/83765.html上一篇: How do I listen to TPL TaskStarted/TaskCompleted ETW events
下一篇: Force a class implementing the interface to define a constant