Подтвердить что ты не робот

Получить список тем

Я хочу перечислить все текущие потоки, но не используя класс List<>. Я хочу динамически наблюдать за потоками. Как я могу это сделать?

4b9b3361

Ответ 1

using System.Diagnostics;

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread thread in currentThreads)    
{
   // Do whatever you need
}

Ответ 2

Способ 1. Получение потоков ОС

Получает список потоков ОС:

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread thread in currentThreads)
{
}

Способ 2: Получить управляемые потоки

Управляемые потоки располагаются поверх потоков ОС. Идентификаторы различны, и теоретически более чем один управляемый поток может сидеть поверх одного потока ОС (хотя я фактически этого не наблюдал).

Оказывается, получение управляемых потоков сложнее, чем это действительно должно быть.

Метод 2.1: Простой код для получения управляемых потоков

Затем вы можете использовать указанный пакет NuGet для присоединения к вашему собственному процессу и прочитать управляемые потоки:

using Microsoft.Diagnostics.Runtime;

using (DataTarget target = DataTarget.AttachToProcess(
    Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive))
{
    ClrRuntime runtime = target.ClrVersions.First().CreateRuntime();
    foreach (ClrThread thread in runtime.Threads)
    {
    }
}

Метод 2.2: пример поиска управляемых потоков по трассировке стека

К сожалению, я не смог найти способ поиска по списку потоков по имени потока.

Однако все не потеряно: вот пример того, как создать управляемый поток, а затем найти его, выполнив поиск по кадрам стека для соответствия в пространстве имен, а затем распечатайте его свойства:

namespace MyTest
{
    int managedThreadId = 0;
    var task = Task.Run(
        () =>
        {
            // Unfortunately, cant see "Testing" anywhere in result returned
            // from NuGet package ClrMD ...
            Thread.CurrentThread.Name = "Testing";
            Thread.Sleep(TimeSpan.FromDays(1));
        });


    // ... so we look for our thread by the first word in this namespace.
    string startOfThisNamespace = this.GetType().Namespace.ToString().Split('.')[0]; // Is "MyTest".
    using (DataTarget target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive))
    {
        ClrRuntime runtime = target.ClrVersions.First().CreateRuntime();

        foreach (ClrThread thread in runtime.Threads)
        {
            IList<ClrStackFrame> stackFrames = thread.StackTrace;

            List<ClrStackFrame> stackframesRelatedToUs = stackFrames
                .Where(o => o.Method != null && o.Method.ToString().StartsWith(startOfThisNamespace)).ToList();

            if (stackframesRelatedToUs.Count > 0)
            {
                Console.Write("ManagedThreadId: {0}, OSThreadId: {1}, Thread: IsAlive: {2}, IsBackground: {3}:\n", thread.ManagedThreadId, thread.OSThreadId, thread.IsAlive, thread.IsBackground);
                Console.Write("- Stack frames related namespace '{0}':\n", startOfThisNamespace);
                foreach (var s in stackframesRelatedToUs)
                {
                    Console.Write("  - StackFrame: {0}\n", s.Method.ToString());
                }
            }
        }
    }
}

Вы также можете найти правильное совпадение, сохранив ManagedThreadId в созданном вами потоке, а затем ищем этот же идентификатор в runtime.Threads.

Тестирование

Протестировано со всеми комбинациями:

  • Visual Studio 2015 SP1
  • .NET 4.5
  • .NET 4.6.0
  • .NET 4.6.1
  • С# 5.0
  • С# 6.0

Ссылки

См. ClrMd генерирует исключение при создании среды выполнения.