System.threading.timer에서 UI에서 UI를 호출 할 때 핸들이 새는 것을 피하는 방법?

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

문제

System.Threading.Timer Leaks Handles의 콜백에서 winforms 컨트롤을 호출하는 것처럼 보입니다. 누구 든지이 문제를 해결하는 방법에 대한 아이디어가 있습니까? 매 순간마다 값을 설문 조사하고 그에 따라 UI를 업데이트해야합니다.

테스트 프로젝트에서 그것이 실제로 누출의 원인인지 확인하기 위해 시도했습니다. 이것은 단순히 다음과 같습니다.

    System.Threading.Timer timer;
    public Form1()
    {
        InitializeComponent();
        timer = new System.Threading.Timer(new System.Threading.TimerCallback(DoStuff), null, 0, 500);
    }
    void DoStuff(object o)
    {
        this.Invoke(new Action(() => this.Text = "hello world"));
    }

Windows 작업 관리자에서 시청하면 2 핸들이 누출됩니다.

도움이 되었습니까?

해결책

UI 스레드에 메시지를 게시하고 손잡이를 생성하며 해당 손잡이를 기다리는 데 호출 된 메소드가 완료된시기를 결정한다는 점에서 BeginInvoke/EndinVoke 쌍과 같은 행위를 호출합니다. "누출"하는 것은이 손잡이입니다. 당신은 이것들이 이름없는 이벤트를 사용하는 것을 볼 수 있습니다 프로세스 탐색기 응용 프로그램이 실행되는 동안 핸들을 모니터링합니다.

iAsyncresult가 edisposable이면 물체를 폐기하면 손잡이를 청소할 수 있습니다. 그렇지 않으므로, 쓰레기 수집기가 실행되어 Iasyncresult 객체의 최종화기를 호출 할 때 핸들이 청소됩니다. Dostuff에 20 건의 호출마다 GC.collect ()를 추가하여이를 볼 수 있습니다. 핸들 카운트는 20 초마다 떨어집니다. 물론 GC.collect ()에 전화를 추가하여 문제를 "해결"하는 것은 잘못된 문제를 해결하는 방법; 쓰레기 수집가가 고유 한 일을하도록하십시오.

그리하지 않으면 필요 호출 호출은 동기화되도록 호출하고, IntinVoke를 호출하는 대신 시작된 발전을 사용하십시오. 엔드-레지 언트는 똑같은 일을하지만 핸들은 만들어 지거나 "누출"되지 않습니다.

다른 팁

시스템을 사용할 수없는 이유가 있습니까? 타이머가 해당 양식에 묶인 경우 호출 할 필요조차 없습니다.

좋아, 나는 조금 더 많은 시간을 주었고 실제로 손잡이가 새지 않는 것처럼 보이며, 그것은 쓰레기 수집가의 불확실한 특성 일뿐입니다. 나는 진드기 당 최대 10ms까지 부딪 쳤고 정말 빨리 올라 갔고 30 초 후에 다시 떨어질 것입니다.

각 콜백에서 수동으로 GC.Collect ()라고 부르는 이론을 확인하기 위해 (실제 프로젝트에서는이 작업을 수행하지 마십시오. 이것은 단지 테스트하는 것이었고, 그것이 나쁜 아이디어 인 이유에 대한 수많은 기사가 있습니다) 핸들 수는 안정적이었습니다.

흥미로운 - 이것은 답이 아니지만 Andrei의 의견을 바탕으로 이것이 유출 된 방식으로 유출되지 않을 것이라고 생각했지만 OP가 언급 한 것과 같은 속도로 누출 처리를한다고 생각했을 것입니다.

System.Threading.Timer timer;
    public Form2()
    {
        InitializeComponent();

    }

    private void UpdateFormTextCallback()
    {
        this.Text = "Hello World!";
    }

    private Action UpdateFormText;

    private void DoStuff(object value)
    {
        this.Invoke(UpdateFormText);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        timer = new System.Threading.Timer(new TimerCallback(DoStuff), null, 0, 500);
        UpdateFormText = new Action(UpdateFormTextCallback);
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top