성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
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'>WPF의 Window 객체를 생성했는데 GC 수집 대상이 안 되는 이유</h1> <p> 질문이 하나 있군요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 안녕하세요 WPF 에서 Window객체가 가비지 콜렉션에 의해 수집되지 않는거 같아서 문의드립니다. ; <a target='tab' href='http://www.sysnet.pe.kr/3/0/4896'>http://www.sysnet.pe.kr/3/0/4896</a> </pre> <br /> 실제로 WPF에서 다음과 같은 간단한 소스 코드로,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.Linq; using System.Windows; namespace WpfApp1 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { foreach (int n in Enumerable.Range(1, 100000)) { Window win = new Window(); } } } } </pre> <br /> 버튼 클릭 몇 번을 하면 OOM 예외가 발생하도록 만들 수 있습니다. 얼핏 보면 new Window만 했으니 GC 대상이 되어야 하지만 그렇지 않은 현상을 보이는 것입니다.<br /> <br /> 이런 경우 생각할 여지가 별로 없으니 다행입니다. 수행된 코드는 어차피 생성자 뿐이 없으니 그 안에서 아마도 다른 루트 객체에 자신의 참조를 추가했을 것입니다. 확인을 위해 .NET Reflector 등으로 소스 코드를 확인하면 답이 나오겠지요.<br /> <br /> 실제로 PresentationFramework 어셈블리의 System.Windows.Window 타입의 생성자를 찾아보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [SecurityCritical] public Window() { this._ownerHandle = IntPtr.Zero; this._updateHwndSize = true; this._updateHwndLocation = true; this._trackMaxWidthDeviceUnits = double.PositiveInfinity; this._trackMaxHeightDeviceUnits = double.PositiveInfinity; this._windowMaxWidthDeviceUnits = double.PositiveInfinity; this._windowMaxHeightDeviceUnits = double.PositiveInfinity; this._actualTop = double.NaN; this._actualLeft = double.NaN; this._dialogOwnerHandle = IntPtr.Zero; this._prePanningLocation = new Point(double.NaN, double.NaN); SecurityHelper.DemandUnmanagedCode(); this._inTrustedSubWindow = false; <span style='color: blue; font-weight: bold'>this.Initialize();</span> } </pre> <br /> 다른 코드는 상관이 없으니 이젠 Initialize를 의심해 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > private void Initialize() { base.BypassLayoutPolicies = true; if (this.IsInsideApp) { if (Application.Current.Dispatcher.Thread == Dispatcher.CurrentDispatcher.Thread) { <span style='color: blue; font-weight: bold'>this.App.WindowsInternal.Add(this);</span> if (this.App.MainWindow == null) { this.App.MainWindow = this; } } else { <span style='color: blue; font-weight: bold'>this.App.NonAppWindowsInternal.Add(this);</span> } } } </pre> <br /> 아하... 여기 있군요. WindowsInternal이든 NonAppWindowsInternal이든 자신을 추가하고 있습니다. 이렇게 this.App 객체가 참조를 잡아 두고 있으니 GC 해제가 안된 것입니다.<br /> <br /> 만약 참조 해제를 하고 싶다면 명시적으로 Close 메서드를 호출해 주면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > foreach (int n in Enumerable.Range(1, 100000)) { Window win = new Window(); <span style='color: blue; font-weight: bold'>win.Close();</span> } </pre> <br /> 그런데, 조금 궁금한 부분이 있군요. 왜 WPF 개발팀은 Window 객체에 명시적으로 자원 해제를 위한 IDisposable 인터페이스를 구현하지 않았을까요?<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
2017
(왼쪽의 숫자를 입력해야 합니다.)