В Visual Studio проекты являются частью решения. Если ваше решение уже находится под контролем исходного кода, каждый проект под ним также должен автоматически находиться под контролем исходного кода при его создании.
Обновлено из комментариев: если ваши проекты находятся в другой папке, чем ваше решение, вам нужно будет вручную добавить их в Git.
Просто чтобы спасти кого-то еще, вот порт вышеупомянутого на 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 наших приложений, так что это легко сделать.
Я написал дампер для проекта, над которым работал в прошлом:
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 , который я написал некоторое время назад.
Существует множество удобных классов в Системе. Диагностика, которая может помочь Вам с отладкой и сбором различной информации отслеживания, т.е. StackTrace.
существует класс Процесса wonky, который может использоваться для получения количества выполнения потоков, но очень немногих деталей. Используйте следующий Отрывок:
Using System.Diagnostics;
var threads = Process.GetCurrentProcess().Threads;
Хорошо после взгляда немного больше кажется, что самый легкий способ получить все текущие стеки через мини-дамп и инструмент как SOS или если Вы выполняете перспективу это .
Удача.
При попытке получить дамп стека, в то время как процесс уже работает (а-ля jstack), существует два метода, как описано здесь :
существует малоизвестный, но эффективный инструмент, названный Управляемый Проводник Стека . Хотя это показывает основной GUI, это может эффективно быть.NET, эквивалентная из jstack, если Вы добавляете к пути; тогда it’s просто вопрос ввода:
mse /s /p <pid>
, я просто считал необходимым взять производственный дамп потока и это работало на меня. Надежда это помогает:-)