8

我正在尝试通过.NET 4.5 中包含的EventSource类在我的 .NET 应用程序中使用Windows 事件跟踪 (ETW) 。我将子类化为并尝试实现一个接口(用于模拟目的),如下所示:EventSourceMyEventSourceIMyEventSource

public interface IMyEventSource
{
  void Test();
}

public class MyEventSource : EventSource, IMyEventSource
{
  public static MyEventSource Log = new MyEventSource();

  [Event(1)]
  public void Test()
  {
    this.WriteEvent(1);
  }
}

当我运行PerfView并执行此代码时,我收到了IndexOutOfRangeExceptionWriteEvent. 如果我通过修改代码来删除接口......

public class MyEventSource : EventSource
{
  public static MyEventSource Log = new MyEventSource();

  [Event(1)]
  public void Test()
  {
    this.WriteEvent(1);
  }
}

...然后一切正常。

这是我在这两种情况下用于测试的代码:

static void Main(string[] args)
{
  MyEventSource.Log.Test();
}

EventSource如果我的子类只是实现一个接口,为什么它会中断?

这是一个相关的帖子

4

5 回答 5

12

在提出问题时,@LarsSkovslund 的回答是正确的。然而,随着微软.Diagnostics.Tracing.EventSource的稳定版本,微软根据他们的博客文章改变了这一点

在 RTM 版本中,我们放宽了一些事件源验证规则,以启用某些高级使用场景。

这方面的两个变化:

  • EventSource 类型现在可以实现接口,以便在高级日志系统中使用事件源类型,这些系统使用接口来定义公共日志目标。

  • 引入了实用程序事件源类型(定义为派生自 EventSource 的抽象类)的概念,以支持在项目中跨多个事件源类型共享代码(例如,用于优化的 WriteEvent() 重载)。

System .Diagnostics.Tracing.EventSource 随 .NET Framework 提供,从.NET 4.6开始支持这些方案

于 2014-04-19T09:03:19.263 回答
5

虽然您不能让事件源实现接口,但可以用另一个实现接口的类来包装它。(这是适配器设计模式的一个实例)

public class EventSourceAdapter : IEventSource
{
    private MyEventSource log;

    public EventSourceAdapter(MyEventSource log)
    {
        this.log = log;
    }

    public void Test()
    { 
        log.Test()
    }
}
} 
于 2013-05-16T07:18:32.587 回答
4

当 EventSource 类基于反射构建其事件结构时,它将仅考虑直接方法,例如,在使用 IMyEventSource 的情况下不考虑继承的成员。

您收到 IndexOutOfRangeException 是因为 WriteEvent 将使用事件 id 参数来查找具有与事件 id 匹配的索引的描述符块,从而在索引不存在时抛出异常。

所以简而言之,不要使用接口来使用 EventSource 定义您的 ETW 事件。

干杯拉尔斯

于 2013-05-01T07:15:13.920 回答
1

截至今天(2014 年 9 月 29 日),原始海报提供的代码不适用于 .NET 4.5 附带的本机代码。它仍然会生成一个“IndexOutOfRange”异常,正如他所说,它只有在 ETW 事件被监视时才会这样做(我正在使用 PerfView)。

也就是说,我使用 nuget.org 的 Microsoft EventSource 库检查了 .NET 4.0 版,他的代码确实可以使用。

接下来,我在 .NET 4.5 版项目中从 nuget 安装了 Microsoft EventSource 库。我确保从 Microsoft.Diagnostics.Tracing.EventSource 继承,而不是从本机 .NET 4.5 库的 System.Diagnostics.Tracing.EventSource 继承。这可行,但我还发现我必须使用 [Microsoft.Diagnostics.Tracing.Event(int)] 属性标记从接口继承的那些方法。

我还观察到一些我无法解释的奇怪行为。有时我的一些事件在 PerfView 中显示为名为“EventID(0)”而不是方法名称。有时我会遇到意外的 IndexOutOfRange 异常。尽我所能猜测先前试验的注册仍保留在内存中。我开始在试验之间重命名我的 EventSource 类,并且我不再遇到这些问题。

JR

于 2014-09-29T19:25:50.770 回答
0

这个问题有一个解决方法(对不起,我不知道如何解释这个问题)。如果您的方法用 装饰,NonEventAttribute您将能够使用您的界面。

你的界面:

public interface IMyEventSource
{
  void Test();
}

和实施:

public class MyEventSource : EventSource, IMyEventSource
{
    public static MyEventSource Log = new MyEventSource();

    [NonEvent]
    public void Test()
    {
        this.InternalTest();
    }

    [Event(1)]
    private void InternalTest()
    {
        this.WriteEvent(1);
    }
}
于 2015-12-15T09:59:22.440 回答