2009-09-28 3 views
1

업데이트 :은 MSDN 문서 How to: Make Thread-Safe Calls to Windows Forms Controls입니다. 그것은 상태 :'크로스 스레드 작업이 유효하지 않음'은 WinForms 응용 프로그램을 죽이지 않습니다.

.NET Framework는 당신이 스레드에 안전하지 않은 방식으로 제어 에 액세스 할 때 을 감지하는 데 도움이됩니다. 디버거에서 응용 프로그램 을 실행하고, 해당 컨트롤을 호출하는 시도를 컨트롤을 만든 것보다 스레드 다른 하는 에서, 디버거가 메세지를 InvalidOperationException이 제기, "제어 컨트롤 이름 에서 액세스 스레드가 생성 된 스레드가 아닌 스레드입니다. "

이 예외는 디버깅 중에 발생하며 런타임에 상황에서 런타임에 안정적으로 발생합니다.

이전의 경험으로는 예외적으로 런타임에 예외가 발생했습니다.

올바른 방향으로 나를 가리키는 Spence에게 감사드립니다.


나는 윈폼 응용 프로그램에서 매우 일반적인 오류가 : 백그라운드 스레드는 UI 컨트롤을 액세스하는 대신 직접() Control.BeginInvoke를 사용하여.

내 문제는 다음과 같습니다. InvalidOperationException "크로스 스레드 작업이 유효하지 않습니다 : 'uxCheckStatus'가 생성 된 스레드 이외의 스레드에서 액세스되었습니다." 배경 스레드의 디버거에서는 WinForms 내부에서 삼켜진다.

나는 백그라운드 스레드와 전체 응용 프로그램을 죽일 것으로 예상된다.

또한 uxCheckStatus.Text = "success";을 트리거하는 코드는 예외가 발생하는/후에 실행되기도합니다. 즉, 라벨 텍스트에 'success'가 표시됩니다. 나는 기본적으로 길을 잃었다. 이 문제가 발생하는 사람은 누구입니까?

완전히 새로운 WinForms 솔루션에서 버튼 하나 (ThreadPool 및 악의적 배경 스레드 용 스레드 모두 사용)에서 재현합니다.

백그라운드 스레드에서 새 InvalidOperationException()을 throw하면 응용 프로그램이 종료됩니다. 그래서 내 유일한 추측은 WinForms이 어딘가에이 특정 예외를 처리하지만 웹에서이 동작에 대한 참조를 찾을 수 없습니다.

나는 .NET 3.5을 실행 VS 2008

답변

3

이것은 의도적으로 설계된 동작입니다. 이것은 런타임 오류가 아니라 코딩 오류입니다. WinForms 개발자는 .Net 2에서 크로스 스레드 코드를 확인한 다음 MDA를 실행하는 코드를 구현할 것이라고 결정했습니다. MDA는 예외는 아니지만 잘못 설계된 코드를 검사합니다.

또한 코드가 릴리스 모드 일 때 MDA가 실행되지 않으며 MDA는 릴리스 될 때가 아니라 테스트 할 때 도움이됩니다.GUI 물건에 대한

업데이트 이벤트 핸들러 :

난 당신이 스레드에 호출 심하게 작성된 응용 프로그램을 다시 작성하고 당신은 예외가 당신을 위해 잡을 것이라고 기대하고 있다고 믿고있어, 나는 제안이 모양은 다음과 같습니다.

public void button_clicked_handler(object sender, EventArgs e) 
{ 
    if(this.InvokeRequired) 
{ 
    this.Invoke(delegateToThisMethod) 
} 
else 
{ 
    //perform method 
} 

이 패턴은 모든 메서드를 catch하여 크로스 스레드 연산에 대해 매끄럽게 만듭니다. 스레드가 코드에 직접 액세스하는 경우 이는 다소 어려울 수 있습니다. 이 문제를 해결하려면 컨트롤의 이름을 변경 한 다음 컨트롤에 속성을 만들어 호출 패턴을 적용 할 수 있습니다. 이전에 매우 펑키 한 크로스 스레드 문제를 해결하기 위해이 작업을 수행했습니다.

행운을 빕니다)

편집 : 그냥 현재 스레드의 동기화 컨텍스트를 확인 명확히하고 싶어하고, 승리는 스레드 비용이 많이 드는 작업입니다 형성한다. 따라서 MDA를 구현 한 이유는 디버그에서 찾을 수 있지만 Windows Forms 컨트롤의 모든 속성이나 메서드에 액세스 할 때마다 릴리스 모드 코드가 느려지지 않는다는 것입니다.

+0

'MDA'란 무엇입니까? 그리고 '디자인'에 대한 언급이 있습니까? 나 자신을 반복하자 : 나는 'Control.BeginInvoke'를 사용해야한다는 것을 안다. 그리고 나는 그것을 사용하는 것을 잊었을 때 어플리케이션이 '실패해야한다'고 예외를 삼키지 않아야한다고 생각합니다. –

+0

좋아요, 디버그 모드에 대해 언급 한 후 MSDN에서이 모드에 대한 참조를 발견했습니다. 감사합니다. –

+0

MSDN에 어딘가에 묻혀 있다는 것을 알고있었습니다. 정보를 질문에 넣었을 때, 많은 사람들이 SO가 유용한 답변의 저장소로 설계되었다는 것을 알지 못합니다. 그런 유지 관리가이 사이트를 훌륭하게 만듭니다. 디버깅에 좋은 행운을 빕니다. 누군가 elses 코드를 읽는 것과 같은 것도 없습니다. – Spence

0

나는 윈폼이 예외를 처리하는 이유/방법에 대한 특정 문서를 알지 못한다. 그러나 이렇게 될 때 애플리케이션을 정상적으로 종료하려면 global exception handler을 고려하십시오.

+0

Application.ThreadException이 호출되지 않습니다. AppDomain.CurrentDomain.UnhandledException은 이론적으로 응용 프로그램을 종료 할 수 있습니다. –

관련 문제