private ThreadPoolItem GetThreadPoolItem(ClrObject item) { ClrType itemType = item.Type; if (itemType.Name == "System.Threading.Tasks.Task") { return(GetTask(item)); } if ( (string.CompareOrdinal(itemType.Name, "System.Threading.QueueUserWorkItemCallback") == 0) || // new to .NET Core (string.CompareOrdinal(itemType.Name, "System.Threading.QueueUserWorkItemCallbackDefaultContext") == 0) ) { return(GetQueueUserWorkItemCallback(item)); } // create a raw information ThreadPoolItem tpi = new ThreadPoolItem() { Type = ThreadRoot.Raw, Address = item.Address, MethodName = itemType.Name }; return(tpi); }
private ThreadPoolItem GetQueueUserWorkItemCallback(ClrObject element) { ThreadPoolItem tpi = new ThreadPoolItem() { Address = (ulong)element, Type = ThreadRoot.WorkItem }; // look for the callback given to ThreadPool.QueueUserWorkItem() // for .NET Core, the callback is stored in a different field _callback var elementType = element.Type; ClrObject callback; if (elementType.GetFieldByName("_callback") != null) { callback = element.ReadObjectField("_callback"); } else if (elementType.GetFieldByName("callback") != null) { callback = element.ReadObjectField("callback"); } else { tpi.MethodName = "[no callback]"; return(tpi); } var target = callback.ReadObjectField("_target"); if (!target.IsValid) { tpi.MethodName = "[no callback target]"; return(tpi); } ClrType targetType = target.Type; if (targetType == null) { tpi.MethodName = $" [target=0x{target.Address}]"; } else { // look for method name tpi.MethodName = BuildDelegateMethodName(targetType, callback); } return(tpi); }
private void DisplayItem(ThreadPoolItem item, Dictionary <string, WorkInfo> tasks, ref int taskCount, Dictionary <string, WorkInfo> workItems, ref int workItemCount) { switch (item.Type) { case ThreadRoot.Task: WriteLine($"0x{item.Address:X16} Task | {item.MethodName}"); UpdateStats(tasks, item.MethodName, ref taskCount); break; case ThreadRoot.WorkItem: WriteLine($"0x{item.Address:X16} Work | {item.MethodName}"); UpdateStats(workItems, item.MethodName, ref workItemCount); break; default: WriteLine($"0x{item.Address:X16} {item.MethodName}"); break; } }
private ThreadPoolItem GetTask(ClrObject task) { ThreadPoolItem tpi = new ThreadPoolItem() { Address = task.Address, Type = ThreadRoot.Task }; // look for the context in m_action._target var action = task.ReadObjectField("m_action"); if (!action.IsValid) { tpi.MethodName = " [no action]"; return(tpi); } var target = action.ReadObjectField("_target"); if (!target.IsValid) { tpi.MethodName = " [no target]"; return(tpi); } tpi.MethodName = BuildDelegateMethodName(target.Type, action); // get the task scheduler if any var taskScheduler = task.ReadObjectField("m_taskScheduler"); if (taskScheduler.IsValid) { var schedulerType = taskScheduler.Type.ToString(); if (string.CompareOrdinal("System.Threading.Tasks.ThreadPoolTaskScheduler", schedulerType) != 0) { tpi.MethodName = $"{tpi.MethodName} [{schedulerType}]"; } } return(tpi); }