EventSource.WriteEventCore(Int32, Int32, EventSource+EventData*) Метод
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Важно!
Этот 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)]
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
Параметры
- eventId
- Int32
Идентификатор события.
- eventDataCount
- Int32
Число элементов данных события.
Структура, содержащая данные события.
- Атрибуты
Комментарии
eventid
значение должно быть больше 0 или меньше 65535, иначе в операции могут возникнуть ошибки. В случае возникновения ошибок можно получить дополнительные сведения об источнике ошибки, проверив поток вывода отладчика, если к событиям запуска процесса подключен отладчик. Вы также можете искать ошибки, сообщаемые в потоке событий ETW, если у вас есть прослушиватель etW в источнике событий, где возникает ошибка.
Этот защищенный метод позволяет пользователям определять новые WriteEvent перегрузки, которые быстрее, чем предоставленные перегрузки. Создание новой перегрузки включает небезопасный код. Основная процедура заключается в выделении стека массива дескрипторов данных событий, соответствующих количеству полезных элементов. Для каждого элемента полезных данных задайте правильный размер и значение в массиве данных события. Вызов WriteEventCore с инициализированным массивом.
В следующем примере показано, как добавить перегрузку WriteEvent , которая принимает четыре аргумента. Например, если у вас есть событие ведения журнала, которое регистрирует строку и 3 целых числа.
[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.