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

Definizione

Importante

Questa API non è conforme a CLS.

Crea un nuovo overload di WriteEvent tramite l'identificatore evento e i dati dell'evento forniti.

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

Parametri

eventId
Int32

Identificatore dell'evento.

eventDataCount
Int32

Numero di elementi dei dati dell'evento.

data
EventSource.EventData

Struttura che contiene i dati dell'evento.

Attributi

Commenti

eventid deve essere maggiore di 0 o minore di 65535 o possono verificarsi errori nell'operazione. Se si verificano errori, è possibile ottenere altre informazioni sull'origine dell'errore controllando il flusso di output del debugger, se è associato un debugger agli eventi di generazione del processo. È anche possibile cercare gli errori segnalati nel flusso di eventi ETW, se si dispone di un listener ETW nell'origine evento in cui si verifica l'errore.

Questo metodo protetto consente agli utenti di definire nuovi WriteEvent overload più veloci rispetto agli overload forniti. La creazione di un nuovo overload comporta codice non sicuro. La procedura di base consiste nello stack allocare una matrice di descrittori di dati degli eventi che corrisponde al numero di elementi del payload. Per ogni elemento del payload, impostare le dimensioni e il valore corretti nella matrice di dati dell'evento. Chiamare WriteEventCore con la matrice inizializzata.

Nell'esempio seguente viene illustrato come aggiungere un WriteEvent overload che accetta quattro argomenti. Ad esempio, se si dispone di un evento di registrazione che registra una stringa e 3 numeri interi.

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

È possibile eseguire questa operazione senza chiamare WriteEventCore, ma sarebbe più lento di quanto debba essere. Questo perché usa matrici e reflection per capire cosa fare. Se si registrano questi dati a una velocità elevata (> 1000/sec), può essere utile fare un supporto rapido, come illustrato nell'esempio seguente. Il metodo shadowsa l'oggetto esistente WriteEvent. Pertanto, il codice del chiamante originale (LogTime) non cambia, ma il compilatore C# userà la versione più specializzata che sarà più veloce.

Per compilare codice unsafe, è necessario specificare l'opzione del compilatore /unsafe (Opzioni del compilatore 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);
        }
    }
}

Queste sono le dimensioni previste e le codifiche dei dati per i tipi serializzabili standard:

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

Si applica a