Как я делаю дамп потока в.NET? (а-ля дампы потока JVM)

В Visual Studio проекты являются частью решения. Если ваше решение уже находится под контролем исходного кода, каждый проект под ним также должен автоматически находиться под контролем исходного кода при его создании.

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

24
задан 10 October 2008 в 05:31
поделиться

4 ответа

Просто чтобы спасти кого-то еще, вот порт вышеупомянутого на c #:

    static void WriteThreadInfo(StringBuilder sw, IEnumerable<Thread> threads)
    {
        foreach(Thread thread in threads)
        {
            if(!thread.IsAlive) continue;
            sw.Append(String.Concat("THREAD NAME: ", thread.Name));

            sw.Append(GetStackTrace(thread));
            sw.AppendLine();
            sw.AppendLine();
        }
    }

    static String GetStackTrace(Thread t)
    {
        t.Suspend();
        var trace1 = new StackTrace(t, true);
        t.Resume();

        String  text1 = System.Environment.NewLine;
        var builder1 = new StringBuilder(255);
        for (Int32 num1 = 0; (num1 < trace1.FrameCount); num1++)
        {
            StackFrame  frame1 = trace1.GetFrame(num1);
            builder1.Append("   at ");
            System.Reflection.MethodBase  base1 = frame1.GetMethod();
            Type  type1 = base1.DeclaringType;
            if (type1 != null)
            {
                String  text2 = type1.Namespace;
                if (text2 != null)
                {
                    builder1.Append(text2);
                    builder1.Append(".");                                                
                }
                builder1.Append(type1.Name);
                builder1.Append(".");
            }
            builder1.Append(base1.Name);
            builder1.Append("(");
            System.Reflection.ParameterInfo [] infoArray1 = base1.GetParameters();
            for (Int32 num2 = 0; (num2 < infoArray1.Length); num2++)
            {
                String text3 = "<UnknownType>";
                if (infoArray1[num2].ParameterType != null)
                {
                                text3 = infoArray1[num2].ParameterType.Name;
                }
                builder1.Append(String.Concat(((num2 != 0) ? ", " : ""), text3, " ", infoArray1[num2].Name));
            }
            builder1.Append(")");
            if (frame1.GetILOffset() != -1)
            {
                String text4 = null;
                try
                {
                    text4 = frame1.GetFileName();
                }
                catch (System.Security.SecurityException)
                {
                }
                if (text4 != null)
                {
                    builder1.Append(String.Concat(" in ", text4, ":line ", frame1.GetFileLineNumber().ToString()));
                }
            }
            if (num1 != (trace1.FrameCount - 1))
            {
                builder1.Append(text1);
            }
        }
        return builder1.ToString();
    }

Я не нашел способа получить список всех управляемых потоков в C # (только ProcessThreads), похоже, вам нужно вести список интересующих вас тем.

Также я обнаружил, что не могу вызвать новую Stacktrace (t, true) для работающего потока, поэтому добавил паузу и возобновил. Очевидно, вам нужно подумать о том, может ли это вызвать проблемы, если вы создадите поток для своего рабочего приложения .

Кстати, мы сделали этот вызов в интерфейсе wcf rest наших приложений, так что это легко сделать.

6
ответ дан 29 November 2019 в 00:20
поделиться

Я написал дампер для проекта, над которым работал в прошлом:

void CrashHandler::WriteThreadInfo(StringWriter* sw, ArrayList* threads, String* type)
{
    sw->WriteLine(type);

    IEnumerator* ie = threads->GetEnumerator();
    while(ie->MoveNext())
    {
        botNETThread* bnt = static_cast<botNETThread*>(ie->Current);
        if(!bnt->IsAlive) continue;
        sw->WriteLine(String::Concat(S"ORIGIN ASSEMBLY: ", bnt->Assembly->FullName));
        sw->WriteLine(String::Concat(S"THREAD NAME: ", (bnt->Name && bnt->Name->Length)?bnt->Name:S"Unnamed thread"));

        sw->Write(GetStackTrace(bnt->_thread));
        sw->WriteLine();
        sw->WriteLine();
    }
}

String* CrashHandler::GetStackTrace(Thread* t)
{

    System::Diagnostics::StackTrace __gc * trace1 = __gc new System::Diagnostics::StackTrace(t, true);

    System::String __gc * text1 = System::Environment::NewLine;
    System::Text::StringBuilder __gc * builder1 = __gc new System::Text::StringBuilder(255);
    for (System::Int32 num1 = 0; (num1 < trace1->FrameCount); num1++)
    {
            System::Diagnostics::StackFrame __gc * frame1 = trace1->GetFrame(num1);
            builder1->Append(S"   at ");
            System::Reflection::MethodBase __gc * base1 = frame1->GetMethod();
            System::Type __gc * type1 = base1->DeclaringType;
            if (type1 != 0)
            {
                System::String __gc * text2 = type1->Namespace;
                if (text2 != 0)
                {
                        builder1->Append(text2);
                        if (builder1 != 0)
                        {
                            builder1->Append(S".");
                        }
                }
                builder1->Append(type1->Name);
                builder1->Append(S".");
            }
            builder1->Append(base1->Name);
            builder1->Append(S"(");
            System::Reflection::ParameterInfo __gc * infoArray1 __gc [] = base1->GetParameters();
            for (System::Int32 num2 = 0; (num2 < infoArray1->Length); num2++)
            {
                System::String __gc * text3 = S"<UnknownType>";
                if (infoArray1[num2]->ParameterType != 0)
                {
                        text3 = infoArray1[num2]->ParameterType->Name;
                }
                builder1->Append(System::String::Concat(((num2 != 0) ? S", " : S""), text3, S" ", infoArray1[num2]->Name));
            }
            builder1->Append(S")");
            if (frame1->GetILOffset() != -1)
            {
                System::String __gc * text4 = 0;
                try
                {
                        text4 = frame1->GetFileName();
                }
                catch (System::Security::SecurityException*)
                {
                }
                if (text4 != 0)
                {
                        builder1->Append(System::String::Concat(S" in ", text4, S":line ", frame1->GetFileLineNumber().ToString()));
                }
            }
            if (num1 != (trace1->FrameCount - 1))
            {
                builder1->Append(text1);
            }
    }
    return builder1->ToString();



}

Вы можете использовать Process.GetCurrentProcess (). Потоки, чтобы получить потоки

И я знаю, что я выплеснул Управляемый C ++, но его достаточно легко следовать. Я беру массив потоков, потому что для своих целей я катагоризовал свои темы. И да, я использовал ранее написанный код стекового фрейма, так как в то время я был новичком в MC ++:)

Весь файл здесь . Это было для бота Diablo II , который я написал некоторое время назад.

1
ответ дан 29 November 2019 в 00:20
поделиться

Существует множество удобных классов в Системе. Диагностика, которая может помочь Вам с отладкой и сбором различной информации отслеживания, т.е. StackTrace.

существует класс Процесса wonky, который может использоваться для получения количества выполнения потоков, но очень немногих деталей. Используйте следующий Отрывок:

Using  System.Diagnostics;

var threads = Process.GetCurrentProcess().Threads;

Хорошо после взгляда немного больше кажется, что самый легкий способ получить все текущие стеки через мини-дамп и инструмент как SOS или если Вы выполняете перспективу это .

Удача.

0
ответ дан 29 November 2019 в 00:20
поделиться

При попытке получить дамп стека, в то время как процесс уже работает (а-ля jstack), существует два метода, как описано здесь :

Используя Управляемый Проводник Стека

существует малоизвестный, но эффективный инструмент, названный Управляемый Проводник Стека . Хотя это показывает основной GUI, это может эффективно быть.NET, эквивалентная из jstack, если Вы добавляете к пути; тогда it’s просто вопрос ввода:

mse /s /p <pid>

Используя Загрузку windbg

  1. и установку соответствующие Средства отладки для версии Windows для Вашей архитектуры (x86/x64/Itanium)
  2. при необходимости в информации о вызовах функции Windows (например, Вы хотите проследить в вызовы ядра), загрузите и установите соответствующие символы. Это не строго необходимо, если Вы просто хотите дамп потока своего собственного кода.
  3. при необходимости в номерах строки или подробной информации удостоверьтесь, что поместили файлы блоков PDB, где отладчик может найти их (обычно, Вы просто помещаете их рядом со своими фактическими блоками).
  4. Запускаются-> Программы-> Средства отладки для Windows [x64]-> Присоединение windbg
  5. отладчик к Вашему рабочему процессу с помощью Загрузки меню
  6. , расширение SOS с ".loadby SOS mscorwks" для.NET 2.0 (" .load SOS" для.NET 1.0/1.1)
  7. Берет использование дампа потока"! eestack"
  8. Отсоединение с помощью ".detach"

, я просто считал необходимым взять производственный дамп потока и это работало на меня. Надежда это помогает:-)

11
ответ дан 29 November 2019 в 00:20
поделиться