나는 내 기억을 되찾고 싶다! 어떻게 제어를 진정으로 처분 할 수 있습니까?
문제
많은 수의 Windows 컨트롤 (버튼 및 레이블 등)을 만드는 응용 프로그램이 있습니다. 그들은 모두 기능을 통해 동적으로 만들어지고 있습니다. 내가 가진 문제는 컨트롤을 제거하고 폐기 할 때 메모리에서 제거되지 않는다는 것입니다.
void loadALoadOfStuff()
{
while(tabControlToClear.Controls.Count > 0)
tabControlToClear.Controls[0].Dispose();
//I even put in:
GC.Collect();
GC.WaitForPendingFinalizers();
foreach(String pagename in globalList)
tabControlToClear.Controls.Add(MakeATab(pagename));
}
TabPage MakeATab(string tabText)
{
TabPage newT = new MakeATab();
newT.Text = tabText;
//Fill page with controls with methods like this
return newT;
}
이제 어떤 이유로, 이것은 단지 내 메모리를 돌려주지 않기 때문에 프로세스가 5 번 실행되면 메모리 위반으로 끝납니다. 나는 대상과 통제 처분을 처음 접했지만 광대 한 그물을 살펴보면 여전히 나에게 어떤 징후도주지 않았으므로 아이디어가 있다면, 나는 그것을 듣게되어 기쁩니다.
업데이트 : 사용자 객체 생성 및 파괴 (TaskManager)를보고 있는데 탭 페이지를 작성하고 클릭 핸들러를 추가하고 패널을 추가하고 클릭 핸들러, 툴팁 및 백 이메지를 사용하여 2 개의 버튼을 추가하는 것을 발견했습니다 (이것이 어디에 있다고 생각합니다. 문제는). 이 앱은 8 개의 새로운 항목을 생성한다고 말하지만 처분을 실행할 때 메모리에서 4 개만 제거합니다. 나는 이벤트 핸들러를 제거하려고 노력했지만 아무런 차이가없는 것 같습니다.
해결되었습니다 !!! 패널에 새 항목을 추가하면서 툴팁을 전달하고있었습니다 (바보이지만 배우고 있습니다). 같은 문제가있는 다른 사람에게 (아래 사람들의 의견과 지시 덕분에. 나는 통제가 진정으로 처분하기 위해 발견했다.
1 : 도구 팁이있는 경우 액세스 가능했는지 확인하십시오! 내가 한 일을하지 마십시오! 예 :
이것은 틀렸다!
TabPage MakeATab(string tabText)
{
TabPage newT = new MakeATab();
ToolTip myTip = new ToolTip();
newT.Text = tabText;
//Fill page with controls with methods like this
myTip.SetToolTip(newT, "Something to say");
return newT;
}
이렇게하면 툴팁에 대한 포인터를 잃어 버리고 툴팁이 연결된 객체의 자녀가 아니기 때문에 (오히려 툴팁이 제어를 강력하게 참조합니다), 컨트롤을 파괴하더라도. 액세스 할 수없는 툴팁은 객체를 살리게합니다.
2 : 무엇이든, Tooltip.removeall ()을 호출하십시오. 이것은 모든 통제와의 관계를 제거합니다. 다른 컨트롤 에이 팁을 사용하는 경우 도구 팁을 잃어 버렸습니다.
3 : 기본 제어에서 내부 컨트롤을 제거합니다. ControlCollection (관리가 아닌 메모리를 사용하는 경우 추측합니다. 앱이 작동하게 만들고 있습니다 ...)
4 : 사용자 정의 이벤트 핸들러를 제거하십시오.
5 : 마지막으로 물체를 처분하십시오. 나는 그것을 잘 수행하는 빠른 재귀 기능을 만들었습니다.
private void RecursiveDispose(Control toDispose)
{
while (toDispose.Controls.Count > 0)
RecursiveDispose(toDispose.Controls[0]);
if (toDispose.BackgroundImage != null)
BackgroundImage = null;
if (toDispose.GetType() == typeof(Button))
toDispose.Click -= [Your Event];
else if (toDispose.GetType() == typeof(TabPage))
toDispose.DoubleClick -= [Your Event];
else if (toDispose.GetType() == typeof(Label))
toDispose.MouseMove -= [Your Event];
toDispose.Dispose();
}
이것은 매우 조잡하고 아마도 훨씬 더 좋은 방법이있을 것입니다. 그러나 누군가가 그것을 생각해 낼 수 없다면, 이것은해야 할 것입니다. 모두 도와 주셔서 감사합니다. 내 프로젝트 전체를 저장했을 수도 있습니다.
해결책
참조를 지우십시오.
while(tabControlToClear.Controls.Count > 0)
{
var tabPage = tabControlToClear.Controls[0];
tabControlToClear.Controls.RemoveAt(0);
tabPage.Dispose();
// Clear out events.
foreach (EventHandler subscriber in tabPage.Click.GetInvocationList())
{
tabPage.Click -= subscriber;
}
}
다른 팁
이 코드 블록에서는 처분하지만 참조를 제거하지는 않습니다.
while(tabControlToClear.Controls.Count > 0)
tabControlToClear.Controls[0].Dispose();
컨트롤이 쓰레기 수집을받을 수 있도록 컨트롤 (Controls Collection 및 등록 된 이벤트 처리기 및 기타 참조)에 대한 모든 참조를 제거해야합니다.
void loadALoadOfStuff()
{
while(tabControlToClear.Controls.Count > 0)
tabControlToClear.Controls[0].Dispose();
//I even put in:
GC.Collect();
GC.WaitForPendingFinalizers();
foreach(String pagename in globalList)
tabControlToClear.Controls.Add(MakeATab(pagename));
}
테스트 방법 끝에있는 모든 탭 인스턴스를 재 할소하고있는 것 같습니다. 따라서 먼저 처분 할 수있는 이점은 없습니다. 마지막 두 줄을 건너 뛰고 도움이되는지 확인하십시오.
지금까지 물체가 해방되지 않는 한 가지 가능한 이유를 언급하는 질문에 대한 많은 훌륭한 답변이있었습니다. 그들은 확인할 가치가있는 모든 것입니다.
그러나 이런 유형의 문제가 발생하면 메모리 프로파일 러 객체에 대한 참조를 추적하기 위해, 마지막으로 메모리 프로파일 러를 볼 때 개미 메모리 프로파일 러 (에서 레 게이트)는 최고 중 하나였습니다. (그들은 이와 같은 단일 문제를 조사하기에 충분히 긴 14 일 꼬리를합니다.)
이것이 약한 사건 패턴이 사용되는 이유 중 하나이지만 완전히 새로운 질문.
(동적으로 수정하면 UI 객체의 수명은 UI가 지뢰밭입니다. TaskManager가 코드가 예상대로 작동하는지 확인하기 위해 잘 수행됨)