Могу ли я получить трассировку стека всех потоков в моем приложении С#?
Я отлаживаю очевидную проблему concurrency в довольно большом приложении, которое я запускаю на работе. Ошибка, о которой идет речь, проявляется только на некоторых более низких машинах после запуска в течение многих (12+) часов, и я никогда не воспроизводил ее в отладчике. Из-за этого мои инструменты отладки в основном ограничены анализом файлов журнала.
С# позволяет легко получить трассировку стека потока, генерирующего исключение, но я хотел бы дополнительно получить трассировки стека из всех остальных потоков, выполняемых в моем AppDomain в момент исключения исключения.
Возможно ли это?
Ответы
Ответ 1
В CodePlex есть инструмент, называемый Managed Stack Explorer (который, как я полагаю, возник из Microsoft). Он использует API отладки и профилирования для захвата трассировок стека потоков в запущенном приложении .Net без необходимости изменения приложения.
Вы можете запустить приложение до тех пор, пока не возникнет проблема, а затем проанализируйте его с помощью этого инструмента, чтобы захватить текущие стеки стека всех запущенных потоков. Преимущество такого подхода заключается в том, что вы оставляете приложение неизменным (инструмент может изменить его поведение), и инструмент свободен.
Ответ 2
Я предлагаю взять дамп процесса, когда возникает исключение. В том же месте, где вы регистрируете вызов исключения, метод MakeDumpFile(), как показано ниже.
Предполагается, что на проблемной машине установлено "Средства отладки для Windows" .
private static void MakeDumpFile()
{
int pid = Process.GetCurrentProcess().Id;
Console.WriteLine("Creating dump for pid " + pid);
//path to adplus executable; ensure you have Debugging tools installed;
string program = @"C:\Program Files (x86)\Debugging Tools for Windows (x86)\adplus.exe";
//args for adplus; ensure the crashdump folder exists!
string args = string.Format(@"-hang -p {0} -o c:\crashdump", pid);
var startInfo = new ProcessStartInfo(program, args);
startInfo.UseShellExecute = false;
startInfo.ErrorDialog = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
var process = Process.Start(startInfo);
Console.WriteLine("The following is output from adplus");
Console.WriteLine(process.StandardOutput.ReadToEnd());
Console.WriteLine("Finished creating dump.");
}
Перейдите в каталог dump, и вы увидите новую папку с файлом в ней с именем FULLDUMP_something_.dmp.
Если вы находитесь на .NET4, вы можете просто перетащить его в VS2010 и проверить все потоки или использовать параллельные потоки, чтобы увидеть, что происходит (это потрясающе!)
Если на NET3.5 или ранее вам нужно будет использовать windbg для анализа. Используйте следующую команду
~ * e! clrstack
чтобы напечатать столбец всех управляемых потоков. Если вам нужна дополнительная помощь, чтобы получить windbg для отправки назад или google для учебника.
Ответ 3
Я не пробовал это сам, но это может быть полезно http://www.debuginspector.com/