EventSource.WriteEventCore(Int32, Int32, EventSource+EventData*) 方法
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
重要
此 API 不符合 CLS 規範。
利用提供的事件識別碼與事件資料產生新的 WriteEvent 超載。
protected:
void WriteEventCore(int eventId, int eventDataCount, System::Diagnostics::Tracing::EventSource::EventData* data);
[System.CLSCompliant(false)]
[System.Security.SecurityCritical]
protected void WriteEventCore(int eventId, int eventDataCount, System.Diagnostics.Tracing.EventSource.EventData* data);
[System.CLSCompliant(false)]
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")]
protected void WriteEventCore(int eventId, int eventDataCount, System.Diagnostics.Tracing.EventSource.EventData* data);
[System.CLSCompliant(false)]
protected void WriteEventCore(int eventId, int eventDataCount, System.Diagnostics.Tracing.EventSource.EventData* data);
[<System.CLSCompliant(false)>]
[<System.Security.SecurityCritical>]
member this.WriteEventCore : int * int * nativeptr<System.Diagnostics.Tracing.EventSource.EventData> -> unit
[<System.CLSCompliant(false)>]
[<System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")>]
member this.WriteEventCore : int * int * nativeptr<System.Diagnostics.Tracing.EventSource.EventData> -> unit
[<System.CLSCompliant(false)>]
member this.WriteEventCore : int * int * nativeptr<System.Diagnostics.Tracing.EventSource.EventData> -> unit
參數
- eventId
- Int32
事件識別碼。
- eventDataCount
- Int32
事件資料項目的數量。
包含事件資料的結構。
- 屬性
備註
eventid 應大於 0 或小於 65535,否則操作中可能出現錯誤。 如果真的發生錯誤,如果你在程序觸發事件上有附帶除錯器,可以透過檢查除錯器的輸出串流來獲得更多錯誤來源的資訊。 如果你在事件來源有 ETW 監聽器,也可以在 ETW 事件串流中尋找錯誤報告。
此受保護方法允許使用者定義 WriteEvent 比現有超載更快的新過載。 產生新的過載涉及不安全的程式碼。 基本程序是堆疊分配一組事件資料描述符陣列,使其與有效載荷項目數量相匹配。 對每個有效載荷項目,在事件資料陣列中設定正確的大小與值。呼叫 WriteEventCore 已初始化的陣列。
以下範例展示了如何加入 WriteEvent 一個接受四個參數的超載。 舉例來說,如果你有一個記錄事件,記錄一個字串和三個整數。
[Event(1)]
public void LogTime(string tag, int hour, int minute, int second)
{
WriteEvent(1, tag, hour, minute, second);
}
你可以不打電話 WriteEventCore就能做到,但速度會比需要的慢。 這是因為它利用陣列和反射來判斷該怎麼做。 如果你以高速率> (每秒 1000 個)記錄這些資料,可以考慮製作一個快速輔助器,如下範例所示。 此方法會跟隨現有 WriteEvent的 。 因此,原始呼叫者程式碼(LogTime)實際上不會改變,但 C# 編譯器會使用更專門且速度更快的版本。
要編譯不安全的程式碼,必須指定 /unsafe (C# 編譯器選項) 編譯器選項。
class AnotherEventSource : EventSource {
[NonEvent]
public unsafe void WriteEvent(int eventId, string arg1, int arg2, int arg3, int arg4)
{
fixed (char* arg1Ptr = arg1)
{
EventData* dataDesc = stackalloc EventData[4];
dataDesc[0].DataPointer = (IntPtr)arg1Ptr;
dataDesc[0].Size = (arg1.Length + 1) * 2; // Size in bytes, including a null terminator.
dataDesc[1].DataPointer = (IntPtr)(&arg2);
dataDesc[1].Size = 4;
dataDesc[2].DataPointer = (IntPtr)(&arg3);
dataDesc[2].Size = 4;
dataDesc[3].DataPointer = (IntPtr)(&arg4);
dataDesc[3].Size = 4;
WriteEventCore(eventId, 4, dataDesc);
}
}
}
以下是標準可序列化型別的預期大小與資料編碼:
// bool arg
int temp = arg ? 1 : 0;
desc.DataPointer = (IntPtr)(&temp);
desc.Size = 4;
// byte arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 1;
// sbyte arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 1;
// char arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 2;
// short arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 2;
// ushort arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 2;
// int arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 4;
// uint arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 4;
// long arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 8;
// ulong arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 8;
// float arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 4;
// double arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 8;
// decimal arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 16;
// Guid arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = 16;
// IntPtr arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = IntPtr.Size;
// UIntPtr arg
desc.DataPointer = (IntPtr)(&arg);
desc.Size = UIntPtr.Size;
// DateTime arg
long fileTime = arg.ToUniversalTime() > new DateTime(1601, 1, 1) ? arg.ToFileTimeUtc() : 0;
desc.DataPointer = (IntPtr)(&fileTime);
desc.Size = 8;
// string arg
fixed(char* ptr = arg)
{
desc.DataPointer = (IntPtr)ptr;
// strings use 2 byte per char UTF16 encoding and a null terminator at the end
// only strings without embedded null characters are supported
desc.Size = (arg.Length + 1) * 2;
}
// byte[] arg
// This one is encoded using two adjacent EventData elements.
fixed(byte* ptr = arg)
{
int length = arg.Length;
desc[i].DataPointer = (IntPtr)(&length);
desc[i].Size = 4;
desc[i + 1].DataPointer = (IntPtr)ptr;
desc[i + 1].Size = arg.Length;
}
// enums should be converted to their underlying type and then serialized
// as byte, short, or int.