나는 내 기억을 되찾고 싶다! 어떻게 제어를 진정으로 처분 할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/2047012

문제

많은 수의 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가 코드가 예상대로 작동하는지 확인하기 위해 잘 수행됨)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top