System.Diagnostics.StackTrace를 사용하여 stacktrace를 가져올 수 있지만 스레드를 일시 중단해야합니다. 일시 중지 및 다시 시작 기능은 더 이상 사용되지 않으므로 더 나은 방법이 존재할 것으로 기대합니다.비 현재 스레드의 스택 추적을 얻는 방법은 무엇입니까?
답변
이 C# 3.0 in a Nutshell에 따르면,이는/다시 시작을 일시 중단 호출 괜찮 몇 가지 상황 중 하나입니다 다음 MDBG 코드베이스는 당신에게 시작을 줄 수 있습니다.
목표 스레드의 협조없이이 작업을 수행하려는 경우 (예 : 스택 추적을 수행하는 동안 세마포어 또는 다른 방법으로 차단하는 메서드를 호출하는 등의 방법으로) 작업을 수행해야합니다. 사용되지 않는 API
가능한 대안은 .NET 디버거에서 사용하는 COM-based ICorDebug 인터페이스를 사용하는 것입니다.
아니, COM이 옵션을 선택하지 않습니다. 일시 중지/이력서는 .NET의 COM 항목보다 더 깔끔한 느낌을줍니다. – bh213
이것은 오래된 스레드이지만 제안 된 솔루션에 대해 경고하고 싶습니다. Suspend 및 Resume 솔루션이 작동하지 않습니다. - 코드 중단시에 Suspend/StackTrace/Resume을 시도하는 데 교착 상태가 발생했습니다.
문제는 StackTrace 생성자가 RuntimeMethodHandle -> MethodBase 변환을 수행하고 이로 인해 잠금을 취하는 내부 MethodInfoCache가 변경된다는 것입니다. 교착 상태는 내가 조사한 실이 반영을하고 있었고 그 자물쇠를 잡고 있었기 때문에 발생했다.
StackTrace 생성자 내에서 일시 중단/다시 시작 작업이 수행되지 않는 것은 불편합니다.이 문제는 쉽게 회피 될 수 있습니다.
완전히 사실입니다. 교착 상태가 발생했습니다. 그래도 해결 방법이있는 것 같지만 (내 대답 참조). –
여기에 지금까지 나를 위해 일한 무슨이다 :
StackTrace GetStackTrace (Thread targetThread)
{
StackTrace stackTrace = null;
var ready = new ManualResetEventSlim();
new Thread (() =>
{
// Backstop to release thread in case of deadlock:
ready.Set();
Thread.Sleep (200);
try { targetThread.Resume(); } catch { }
}).Start();
ready.Wait();
targetThread.Suspend();
try { stackTrace = new StackTrace (targetThread, true); }
catch { /* Deadlock */ }
finally
{
try { targetThread.Resume(); }
catch { stackTrace = null; /* Deadlock */ }
}
return stackTrace;
}
이 교착되면 교착 상태가 자동으로 해제하고 널 추적을 다시 얻을. (그런 다음 다시 호출 할 수 있습니다.)
몇 일간의 테스트 후 필자는 Core i7 시스템에서 교착 상태를 만들 수있었습니다. 하지만 교착 상태는 CPU가 100 %로 실행될 때 단일 코어 VM에서 일반적으로 발생합니다.
두 번째'ManualResetEvent'를 사용하여 targetThread를 피할 수 있습니다.이력서는() 실행하고 예외를 throw되는 * 때마다 * ... 경우 { 시도 {targetThread.Resume() (noDeadLockSafeGuard.WaitOne (200)!); } 캐치 {} } –
가 여전히 교착 상태에 대한 작은 위험이 남아 런타임은 "ready.Wait()"와 "targetThread.Suspend()"사이의 주요 스레드를 일시 중단하기로 결정하면, 당신은 여전히있을 수 있습니다 폴백 이후 교착 상태 - 스레드가 이미 종료되었습니다. IMO는 메인 스레드가 안전하게 함수를 빠져 나왔다는 시그널이있을 때만 남겨진 unlock-thread에 루프가 있어야합니다. – Andreas
것은 Thread.suspend()와 경고를 오류로 사용하는 사람의 #pragma는'비활성화 0618'' 방법 전에 및 경고'' 를 사용해야합니다 그래서 Thread.resume가()는 프레임 워크에서 사용되지 않는 것으로 표시됩니다 이 코드를 컴파일하려면'#pragma warning restore 0618'' 이 필요합니다. –
내 의견에서 언급했듯이 제안 된 솔루션은 여전히 교착 상태에 대한 가능성이 매우 낮습니다. 아래 내 버전을 찾으십시오.
private static StackTrace GetStackTrace(Thread targetThread) {
using (ManualResetEvent fallbackThreadReady = new ManualResetEvent(false), exitedSafely = new ManualResetEvent(false)) {
Thread fallbackThread = new Thread(delegate() {
fallbackThreadReady.Set();
while (!exitedSafely.WaitOne(200)) {
try {
targetThread.Resume();
} catch (Exception) {/*Whatever happens, do never stop to resume the target-thread regularly until the main-thread has exited safely.*/}
}
});
fallbackThread.Name = "GetStackFallbackThread";
try {
fallbackThread.Start();
fallbackThreadReady.WaitOne();
//From here, you have about 200ms to get the stack-trace.
targetThread.Suspend();
StackTrace trace = null;
try {
trace = new StackTrace(targetThread, true);
} catch (ThreadStateException) {
//failed to get stack trace, since the fallback-thread resumed the thread
//possible reasons:
//1.) This thread was just too slow (not very likely)
//2.) The deadlock ocurred and the fallbackThread rescued the situation.
//In both cases just return null.
}
try {
targetThread.Resume();
} catch (ThreadStateException) {/*Thread is running again already*/}
return trace;
} finally {
//Just signal the backup-thread to stop.
exitedSafely.Set();
//Join the thread to avoid disposing "exited safely" too early. And also make sure that no leftover threads are cluttering iis by accident.
fallbackThread.Join();
}
}
}
내 생각의 ManualResetEventSlim "fallbackThreadReady는"정말 필요하지 않습니다,하지만 왜이 민감한 경우 어떤 위험을 감수? 이 과거에 지원되는 동작처럼
그것은 보이지만, 불행히도, Microsoft는이 쓰이지 : https://msdn.microsoft.com/en-us/library/t2k35tat(v=vs.110).aspx이
- 1. 모든 스레드의 스택 추적을 얻으십시오.
- 2. 현재 스레드의 ProcessThread.TotalProcessorTime을 얻는 방법은
- 3. 응용 프로그램의 현재 스택 추적을 인쇄하는 쉬운 방법은 무엇입니까?
- 4. .NET의 현재 스택 추적을 예외없이 인쇄하는 방법은 무엇입니까?
- 5. FireFox 확장의 오류에서 스택 추적을 얻는 방법은 무엇입니까?
- 6. R : 눈 패키지에서 스택 추적을 얻는 방법
- 7. 스레드의 상태를 얻는 방법은 무엇입니까?
- 8. 예외 스택 추적을 인쇄해야합니까?
- 9. UI에 스택 추적을 표시하는 방법은 무엇입니까?
- 10. 미니 덤프에서 스택 추적을 추출하는 방법은 무엇입니까?
- 11. 기존 .NET 스레드의 스택 크기를 얻는 방법
- 12. VS 2008 디버거를 사용하여 모든 스택 추적을 얻는 방법
- 13. Android에서 충돌 스택 추적을 가져 오는 가장 쉬운 방법은 무엇입니까?
- 14. 현재 스레드의 아파트 상태를 확인하는 방법은 무엇입니까?
- 15. 오이 스택 추적을 없애기
- 16. 웹 시작에서 실행중인 클라이언트에서 Java 스택 추적을 얻는 방법?
- 17. 다중 스레드 C++ 실행 프로세스에서 스레드 추적을 얻는 방법은 무엇입니까?
- 18. 현재 ProcessID를 얻는 방법은 무엇입니까?
- 19. SBT를 통해 스펙을 실행할 때 스택 추적을 제거하는 방법은 무엇입니까?
- 20. 전체 스택 추적을 예외로 인쇄하는 방법은 무엇입니까? 한 곳에서
- 21. 관리 코드에서 잡힌 네이티브 예외에서 기본 스택 추적을 얻는 방법
- 22. 충돌하는 혼합 모드 exe/dll에서 전체 스택 추적을 얻는 방법?
- 23. 승객의 모든 실행중인 루비 스레드에 스택 추적을 얻는 방법
- 24. OCaml에서 스택 추적을 얻으려면 어떻게해야합니까?
- 25. 예외를 던지지만 스택 추적을 유지하십시오.
- 26. 분할 오류의 스택 추적을 이해하십시오.
- 27. 스택 추적을 보존하는 JavaScript 재실행
- 28. 예외가 스택 추적을 지 웁니다.
- 29. Specman에서 스택 추적을 얻으려면 어떻게해야합니까?
- 30. 스택 추적을 해석하는 데 도움이됩니다.
그것이 내가 한 일입니다. – bh213
힘든 교착 상태가 발생하지 않도록주의하십시오. 스레드가 필요한 잠금 장치를 보유하고있는 동안 스레드를 일시 중단하면 교착 상태가 발생합니다. 가장 일반적인 원인은 스레드가 스트림을 공유하는 것입니다 (예 : 콘솔이나 유사한 장치에 쓰기). –