private void Reset() { if (!CanReset) { throw new InvalidOperationException("Event stream is not resetable (e.g. real time)."); } if (handles != null) { for (int i = 0; i < handles.Length; i++) { if (handles[i] != TraceEventNativeMethods.INVALID_HANDLE_VALUE) { TraceEventNativeMethods.CloseTrace(handles[i]); handles[i] = TraceEventNativeMethods.INVALID_HANDLE_VALUE; } // Annoying. The OS resets the LogFileMode field, so I have to set it up again. if (!useClassicETW) { logFiles[i].LogFileMode = TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD; logFiles[i].LogFileMode |= TraceEventNativeMethods.PROCESS_TRACE_MODE_RAW_TIMESTAMP; } handles[i] = TraceEventNativeMethods.OpenTrace(ref logFiles[i]); if (handles[i] == TraceEventNativeMethods.INVALID_HANDLE_VALUE) { Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error()); } } } }
/// <summary> /// see Dispose pattern /// </summary> protected override void Dispose(bool disposing) { // We only want one thread doing this at a time. lock (this) { stopProcessing = true; if (handles != null) { foreach (ulong handle in handles) { if (handle != TraceEventNativeMethods.INVALID_HANDLE_VALUE) { TraceEventNativeMethods.CloseTrace(handle); } } handles = null; } if (convertedHeader != null) { Marshal.FreeHGlobal((IntPtr)convertedHeader); convertedHeader = null; } traceLoggingEventId.Dispose(); // logFiles = null; Keep the callback delegate alive as long as possible. base.Dispose(disposing); } }
// Process is called after all desired subscriptions have been registered. /// <summary> /// Processes all the events in the data source, issuing callbacks that were subscribed to. See /// #Introduction for more /// </summary> /// <returns>false If StopProcesing was called</returns> // [SecuritySafeCritical] public override bool Process() { stopProcessing = false; if (processTraceCalled) { Reset(); } processTraceCalled = true; if (fileNames != null) { foreach (var fileName in fileNames) { if (handles != null) { Debug.Assert(handles.Length == 1); if (handles[0] != TraceEventNativeMethods.INVALID_HANDLE_VALUE) { TraceEventNativeMethods.CloseTrace(handles[0]); } } Initialize(fileName, TraceEventSourceType.FileOnly); if (!ProcessOneFile()) { OnCompleted(); Debug.Assert(sessionEndTimeQPC != long.MaxValue); // Not a real time session return(false); } } OnCompleted(); Debug.Assert(sessionEndTimeQPC != long.MaxValue); // Not a real time session return(true); } else { var ret = ProcessOneFile(); // If the session is real time, set he sessionEndTime (since the session is stopping). if (sessionEndTimeQPC == long.MaxValue) { sessionEndTimeQPC = QPCTime.GetUTCTimeAsQPC(DateTime.UtcNow); } OnCompleted(); return(ret); } }
// Process is called after all desired subscriptions have been registered. /// <summary> /// Processes all the events in the data source, issuing callbacks that were subscribed to. See /// #Introduction for more /// </summary> /// <returns>false If StopProcesing was called</returns> // [SecuritySafeCritical] public override bool Process() { stopProcessing = false; if (processTraceCalled) { Reset(); } processTraceCalled = true; if (fileNames != null) { foreach (var fileName in fileNames) { if (handles != null) { Debug.Assert(handles.Length == 1); if (handles[0] != TraceEventNativeMethods.INVALID_HANDLE_VALUE) { TraceEventNativeMethods.CloseTrace(handles[0]); } } Initialize(fileName, TraceEventSourceType.FileOnly); if (!ProcessOneFile()) { OnCompleted(); return(false); } } OnCompleted(); return(true); } else { var ret = ProcessOneFile(); OnCompleted(); return(ret); } }