Teilen über


EventSource.WriteEventCore(Int32, Int32, EventSource+EventData*) Methode

Definition

Wichtig

Diese API ist nicht CLS-kompatibel.

Erstellt eine neue WriteEvent-Überladung mithilfe des bereitgestellten Ereignisbezeichners und den Ereignisdaten.

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)]
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)>]
member this.WriteEventCore : int * int * nativeptr<System.Diagnostics.Tracing.EventSource.EventData> -> unit

Parameter

eventId
Int32

Der Ereignisbezeichner.

eventDataCount
Int32

Die Anzahl der Ereignisdatenelemente.

data
EventSource.EventData

Ein Struktur, die die Ereignisdaten enthält.

Attribute

Hinweise

eventid sollte größer als 0 oder kleiner als 65535 sein, da fehler im Vorgang auftreten können. Wenn Fehler auftreten, können Sie weitere Informationen zur Fehlerquelle abrufen, indem Sie den Ausgabestream des Debuggers überprüfen, wenn ein Debugger an die Prozessauslösungsereignisse angefügt ist. Sie können auch nach Fehlern suchen, die im ETW-Ereignisstream gemeldet wurden, wenn Sie über einen ETW-Listener für die Ereignisquelle verfügen, in der der Fehler auftritt.

Mit dieser geschützten Methode können Benutzer neue WriteEvent Überladungen definieren, die schneller als die bereitgestellten Überladungen sind. Das Erstellen einer neuen Überladung beinhaltet unsicheren Code. Das grundlegende Verfahren besteht darin, ein Array von Ereignisdatendeskriptoren zu stapeln, die der Anzahl der Nutzlastelemente entsprechen. Legen Sie für jedes Nutzlastelement die richtige Größe und den richtigen Wert im Ereignisdatenarray fest. Rufen Sie WriteEventCore mit dem initialisierten Array auf.

Das folgende Beispiel zeigt, wie Sie eine WriteEvent Überladung hinzufügen, die vier Argumente akzeptiert. Ein Beispiel wäre, wenn Sie über ein Protokollierungsereignis verfügen, das eine Zeichenfolge und 3 ganze Zahlen protokolliert.

[Event(1)]
public void LogTime(string tag, int hour, int minute, int second)
{
    WriteEvent(1, tag, hour, minute, second);
}

Sie könnten dies tun, ohne aufzurufen WriteEventCore, aber es wäre langsamer als es sein muss. Das liegt daran, dass arrays und reflektion verwendet werden, um herauszufinden, was zu tun ist. Wenn Sie diese mit einer hohen Rate (> 1000 /s) protokollieren, kann es sich lohnen, ein schnelles Hilfsprogramm zu erstellen, wie im folgenden Beispiel gezeigt. Die -Methode überschatt die vorhandene WriteEvent. Daher ändert sich der ursprüngliche Aufrufercode (LogTime) nicht, aber der C#-Compiler verwendet die spezialisiertere Version, die schneller ist.

Um unsicheren Code zu kompilieren, müssen Sie die Compileroption /unsafe (C#-Compileroptionen) angeben.

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);
        }
    }
}

Dies sind die erwarteten Größen und Datencodierungen für serialisierbare Standardtypen:

// 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.

Gilt für: