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

Definicja

Ważne

Ten interfejs API nie jest zgodny ze specyfikacją CLS.

Tworzy nowe WriteEvent przeciążenie przy użyciu podanego identyfikatora zdarzenia i danych zdarzenia.

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

Parametry

eventId
Int32

Identyfikator zdarzenia.

eventDataCount
Int32

Liczba elementów danych zdarzenia.

data
EventSource.EventData

Struktura zawierająca dane zdarzenia.

Atrybuty

Uwagi

eventid wartość powinna być większa niż 0 lub mniejsza niż 65535 lub błędy mogą wystąpić w operacji. Jeśli wystąpią błędy, możesz uzyskać więcej informacji o źródle błędu, sprawdzając strumień wyjściowy debugera, jeśli masz debuger dołączony do zdarzeń wyzwalania procesu. Możesz również wyszukać błędy zgłoszone w strumieniu zdarzeń ETW, jeśli masz odbiornik ETW w źródle zdarzeń, w którym występuje błąd.

Ta chroniona metoda umożliwia użytkownikom definiowanie nowych WriteEvent przeciążeń, które są szybsze niż podane przeciążenia. Tworzenie nowego przeciążenia obejmuje niebezpieczny kod. Podstawową procedurą jest przydzielenie tablicy deskryptorów danych zdarzeń pasujących do liczby elementów ładunku. Dla każdego elementu ładunku ustaw prawidłowy rozmiar i wartość w tablicy danych zdarzenia. Wywołaj metodę WriteEventCore z zainicjowaną tablicą.

W poniższym przykładzie pokazano, jak dodać WriteEvent przeciążenie, które akceptuje cztery argumenty. Przykładem może być zdarzenie rejestrowania, które rejestruje ciąg i 3 liczby całkowite.

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

Można to zrobić bez wywołania WriteEventCoremetody , ale byłoby wolniejsze niż musi być. Dzieje się tak, ponieważ używa tablic i odbicia, aby dowiedzieć się, co robić. Jeśli rejestrujesz je z wysoką szybkością (> 1000 / s), warto zrobić szybki pomocnik, jak pokazano w poniższym przykładzie. Metoda w tle istniejącego WriteEventelementu . W związku z tym oryginalny kod wywołujący (LogTime) nie zmienia się, ale kompilator języka C# będzie używać bardziej wyspecjalizowanej wersji, która będzie szybsza.

Aby skompilować niebezpieczny kod, należy określić /niebezpieczne (opcje kompilatora języka C#) opcję kompilatora .

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

Są to oczekiwane rozmiary i kodowanie danych dla standardowych typów możliwych do serializacji:

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

Dotyczy