성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - 닷넷 코어에서 다른 스레드의 callstack을 구하는 방법</h1> <p> .NET Framework와는 다르게,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 다른 스레드의 호출 스택 덤프 구하는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/802'>https://www.sysnet.pe.kr/2/0/802</a> </pre> <br /> .NET Core에서는 기본적으로 System.Diagnostics.StackTrace 타입이 없습니다. 그것을 사용하려면 명시적으로 Nuget으로부터 System.Diagnostics.StackTrace를 참조 추가해야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Install-Package <a target='tab' href='https://www.nuget.org/packages/System.Diagnostics.StackTrace/'>System.Diagnostics.StackTrace</a> </pre> <br /> 그런데, nuget의 StackTrace 타입에는 Thread 타입을 받는 생성자가 없습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Thread newThread = new Thread(Run); newThread.Start(); newThread.Suspend(); System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(<span style='color: blue; font-weight: bold'>/* newThread, */</span> false); newThread.Resume(); </pre> <br /> 그래서 다른 스레드의 호출 스택을 받을 방법이 없습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이를 우회할 수 있는 현실적인 방법으로는 그나마 ClrMD가 적당해 보입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > .NET 스레드 콜 스택 덤프 (7) - <a target='tab' href='https://github.com/Microsoft/clrmd'>ClrMD(Microsoft.Diagnostics.Runtime)</a>를 이용한 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/11043'>https://www.sysnet.pe.kr/2/0/11043</a> </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Install-Package <a target='tab' href='https://www.nuget.org/packages/Microsoft.Diagnostics.Runtime'>Microsoft.Diagnostics.Runtime</a> </pre> <br /> 다음은 .NET Core에서의 사용 예제입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using Microsoft.Diagnostics.Runtime; using System; using System.Diagnostics; using System.Threading; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Console.WriteLine("Main: " + Thread.CurrentThread.ManagedThreadId); Thread t = new Thread(CallMethod); t.Start(); DoLoop(); } private static void DoLoop() { int i = 0; while (true) { Console.WriteLine("==================================================" + (i++).ToString()); Thread.Sleep(1000); } } private static void CallMethod(object obj) { while (true) { var pid = Process.GetCurrentProcess().Id; using (var dataTarget = DataTarget.AttachToProcess(pid, false)) { ClrInfo runtimeInfo = dataTarget.ClrVersions[0]; using (ClrRuntime runtime = runtimeInfo.CreateRuntime()) { foreach (var t in runtime.Threads) { foreach (ClrStackFrame st in t.EnumerateStackTrace()) { // Console.WriteLine($"{t.ManagedThreadId} {st.Method} {st.Kind} at 0x{st.InstructionPointer.ToString("x")}"); Console.WriteLine(st); } Console.WriteLine(); } } } } } } } /* 출력 결과 Console.WriteLine($"{t.ManagedThreadId} {st.Method} {st.Kind} at 0x{st.InstructionPointer.ToString("x")}"); 1 Runtime at 0x0 1 System.Threading.Thread.Sleep(Int32) ManagedMethod at 0x7ff83de0b92b 1 ConsoleApp1.Program.DoLoop() ManagedMethod at 0x7ff7e1e46347 1 ConsoleApp1.Program.Main(System.String[]) ManagedMethod at 0x7ff7e1e41046 1 Runtime at 0x7ff841953903 1 Runtime at 0x7ff841953903 2 Runtime at 0x0 3 ManagedMethod at 0x0 */ /* 출력 결과 Console.WriteLine(st); [HelperMethodFrame] System.Threading.Thread.Sleep(Int32) ConsoleApp1.Program.DoLoop() ConsoleApp1.Program.Main(System.String[]) [GCFrame] [GCFrame] [DebuggerU2MCatchHandlerFrame] */ </pre> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1697&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> <br /> 보는 바와 같이 순수 Managed 영역의 호출 스택만 정상적으로 값을 받아올 수 있고 그 외 Native/Runtime 등의 호출 스택 정보는 알 수 없습니다. 또한, (아마도 향후 지원할지는 모르겠지만) 소스 코드 라인 정보도 구할 방법이 없습니다.<br /> <br /> 게다가, 이전 버전(1.1.142101)과는 달리 현재 2.0.161401에서는 저렇게 무한 루프를 돌며 호출 스택을 구하면 어느 순간 화면에 "[Unknown Frame]"이 반복되며 더 이상 정상적인 동작을 하지 않는 문제가 있습니다. (그러니까, "그나마" 나은 방법입니다. ^^;)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
9539
(왼쪽의 숫자를 입력해야 합니다.)