protected override void Update() { // Load symbols if they are not already loaded. this.LoadSymbols(); var threads = Windows.GetProcessThreads(_pid); Dictionary <int, ThreadItem> newdictionary = new Dictionary <int, ThreadItem>(this.Dictionary); if (threads == null) { threads = new Dictionary <int, SystemThreadInformation>(); } // look for dead threads foreach (int tid in Dictionary.Keys) { if (!threads.ContainsKey(tid)) { ThreadItem item = this.Dictionary[tid]; if (item.ThreadQueryLimitedHandle != null) { item.ThreadQueryLimitedHandle.Dispose(); } this.OnDictionaryRemoved(item); newdictionary.Remove(tid); } } // Get resolve results. _messageQueue.Listen(); // look for new threads foreach (int tid in threads.Keys) { var t = threads[tid]; if (!Dictionary.ContainsKey(tid)) { ThreadItem item = new ThreadItem(); item.RunId = this.RunCount; item.Tid = tid; item.ContextSwitches = t.ContextSwitchCount; item.WaitReason = t.WaitReason; try { item.ThreadQueryLimitedHandle = new ThreadHandle(tid, Program.MinThreadQueryRights); try { item.PriorityI = (int)item.ThreadQueryLimitedHandle.GetBasePriorityWin32(); item.Priority = item.ThreadQueryLimitedHandle.GetBasePriorityWin32().ToString(); } catch { } if (KProcessHacker.Instance != null) { try { item.IsGuiThread = KProcessHacker.Instance.KphGetThreadWin32Thread(item.ThreadQueryLimitedHandle) != 0; } catch { } } if (OSVersion.HasCycleTime) { try { item.Cycles = item.ThreadQueryLimitedHandle.GetCycleTime(); } catch { } } } catch { } if (KProcessHacker.Instance != null && item.ThreadQueryLimitedHandle != null) { try { item.StartAddressI = KProcessHacker.Instance.GetThreadStartAddress(item.ThreadQueryLimitedHandle).ToIntPtr(); } catch { } } else { try { using (ThreadHandle thandle = new ThreadHandle(tid, ThreadAccess.QueryInformation)) { item.StartAddressI = thandle.GetWin32StartAddress(); } } catch { item.StartAddressI = t.StartAddress; } } if (_moduleLoadCompletedEvent.Wait(0)) { try { item.StartAddress = this.GetThreadBasicStartAddress( item.StartAddressI.ToUInt64(), out item.StartAddressLevel); } catch { } } if (string.IsNullOrEmpty(item.StartAddress)) { item.StartAddress = Utils.FormatAddress(item.StartAddressI); item.StartAddressLevel = SymbolResolveLevel.Address; } this.QueueThreadResolveStartAddress(tid, item.StartAddressI.ToUInt64()); newdictionary.Add(tid, item); this.OnDictionaryAdded(item); } // look for modified threads else { ThreadItem item = Dictionary[tid]; ThreadItem newitem = item.Clone() as ThreadItem; newitem.JustResolved = false; newitem.ContextSwitchesDelta = t.ContextSwitchCount - newitem.ContextSwitches; newitem.ContextSwitches = t.ContextSwitchCount; newitem.WaitReason = t.WaitReason; try { newitem.PriorityI = (int)newitem.ThreadQueryLimitedHandle.GetBasePriorityWin32(); newitem.Priority = newitem.ThreadQueryLimitedHandle.GetBasePriorityWin32().ToString(); } catch { } if (KProcessHacker.Instance != null) { try { newitem.IsGuiThread = KProcessHacker.Instance.KphGetThreadWin32Thread(newitem.ThreadQueryLimitedHandle) != 0; } catch { } } if (OSVersion.HasCycleTime) { try { ulong thisCycles = newitem.ThreadQueryLimitedHandle.GetCycleTime(); newitem.CyclesDelta = thisCycles - newitem.Cycles; newitem.Cycles = thisCycles; } catch { } } if (newitem.StartAddressLevel == SymbolResolveLevel.Address) { if (_moduleLoadCompletedEvent.Wait(0)) { newitem.StartAddress = this.GetThreadBasicStartAddress( newitem.StartAddressI.ToUInt64(), out newitem.StartAddressLevel); } // If we couldn't resolve it to a module+offset, // use the StartAddress (instead of the Win32StartAddress) // and queue the resolve again. if ( item.StartAddressLevel == SymbolResolveLevel.Address && item.JustResolved) { if (item.StartAddressI != t.StartAddress) { item.StartAddressI = t.StartAddress; this.QueueThreadResolveStartAddress(tid, item.StartAddressI.ToUInt64()); } } } if ( newitem.ContextSwitches != item.ContextSwitches || newitem.ContextSwitchesDelta != item.ContextSwitchesDelta || newitem.Cycles != item.Cycles || newitem.CyclesDelta != item.CyclesDelta || newitem.IsGuiThread != item.IsGuiThread || newitem.Priority != item.Priority || newitem.StartAddress != item.StartAddress || newitem.WaitReason != item.WaitReason || item.JustResolved ) { newdictionary[tid] = newitem; this.OnDictionaryModified(item, newitem); } } } Dictionary = newdictionary; }