성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
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# - Thread.Suspend 호출 시 응용 프로그램 hang 현상을 해결하기 위한 시도</h1> <p> 지난 글에서 Thread.Suspend 호출 시 Resume까지의 시간 동안 메모리 할당이 발생하면 hang 현상이 발생할 수 있다고 설명했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - Thread.Suspend 호출 시 응용 프로그램 hang 현상 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11473'>http://www.sysnet.pe.kr/2/0/11473</a> windbg - Thread.Suspend 호출 시 응용 프로그램 hang 현상에 대한 덤프 분석 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11475'>http://www.sysnet.pe.kr/2/0/11475</a> </pre> <br /> 그러니까, 관건은 GC가 발생하는 동안에는 Thread.Suspend를 호출해서는 안 되는 것입니다. 그렇다면, 혹시 GC.WaitForFullGCApproach / GC.WaitForFullGCComplete을 이용해 GC가 임박했을 때 Thread.Suspend를 하지 않도록 만드는 것도 가능하지 않을까요?<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > How to receive a full GC notification with .NET 4.0 ; <a target='tab' href='https://learn.microsoft.com/en-us/archive/blogs/albulank/how-to-receive-a-full-gc-notification-with-net-4-0'>https://learn.microsoft.com/en-us/archive/blogs/albulank/how-to-receive-a-full-gc-notification-with-net-4-0</a> GC.RegisterForFullGCNotification(Int32, Int32) Method ; <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/api/system.gc.registerforfullgcnotification'>https://learn.microsoft.com/en-us/dotnet/api/system.gc.registerforfullgcnotification</a> </pre> <br /> 이를 바탕으로 다음과 같이 GC가 구동하려고 할 때 GC.WaitForFullGCApproach ~ GC.WaitForFullGCComplete 호출 구간에는 Thread.Suspend를 하지 못하도록 변경을 해봤습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > static volatile bool _safeStackTrace; static void Main(string[] args) { GC.RegisterForFullGCNotification(10, 10); _safeStackTrace = true; Thread thWaitForFullGC = new Thread(GCNotifyProc); thWaitForFullGC.IsBackground = true; thWaitForFullGC.Start(); Program pg = new Program(); pg.Start(); Console.ReadLine(); } static private void GCNotifyProc() { while (true) { var gcApproachStatus = <span style='color: blue; font-weight: bold'>GC.WaitForFullGCApproach</span>(); if (gcApproachStatus == GCNotificationStatus.Succeeded) { <span style='color: blue; font-weight: bold'>_safeStackTrace = false</span>; GC.Collect(); } else { return; } var gcCompleteStatus = <span style='color: blue; font-weight: bold'>GC.WaitForFullGCComplete</span>(); if (gcCompleteStatus == GCNotificationStatus.Succeeded) { <span style='color: blue; font-weight: bold'>_safeStackTrace = true</span>; } else { return; } } } private static string GetCallStack(Thread t) { string result = ""; try { // ...[생략]... if (_safeStackTrace == true) { trace = new System.Diagnostics.StackTrace(t, false); result = trace.ToString(); } // ...[생략]... } catch { } return result; } </pre> <br /> 하지만, 실제로 해보면 얼마 못 가서 ^^; 멈춥니다. 왜냐하면 GC.WaitForFullGCApproach 이후 _safeStackTrace = false를 설정하기 전, 다른 스레드가 이미 "new System.Diagnostics.StackTrace(t, false)" 코드로 진입해 힙 할당을 초래하는 코드를 실행할 수 있기 때문입니다. 어쩌면 이런 짧은 시간에 발생하는 경합 문제는 RegisterForFullGCNotification의 threshold 값을 10보다 높게 잡아 여유를 주거나, 테스트 자체의 부하를 조금 낮추면 확률을 줄일 수 있을 것입니다.<br /> <br /> 하지만 그런 시도를 하기가 좀 무의미한 면이 있는데요, 사실 별로 현실성이 없다는 생각이 들었습니다. 왜냐하면, GC.WaitForFullGCApproach, GC.WaitForFullGCComplete 메서드가 동작하도록 하려면 반드시 "Concurrent GC" 모드를 꺼야 하기 때문입니다. 즉, app.config 파일에 다음과 같은 항목을 포함시켜야만 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <?xml version="1.0" encoding="utf-8"?> <configuration> <startup> <supportedRuntime version="v4.0"/> </startup> <runtime> <gcServer enabled="true"/> <span style='color: blue; font-weight: bold'><gcConcurrent enabled="false"/></span> </runtime> </configuration> </pre> <br /> 독립 프로그램을 만드는 경우라면 저것도 방법일 수 있겠지만, 라이브러리 개발자들에게는 전혀 현실성이 없는 요구 사항입니다.<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1504&boardid=331301885'>첨부 파일은 이 글의 테스트 코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
7774
(왼쪽의 숫자를 입력해야 합니다.)