2011-11-06 2 views
2

이것은 내 첫 번째 스택 질문이므로 내 형식이나 예의가 조금이라도 미리 사과드립니다.단위 테스트에서 '크로스 스레드 연산이 유효하지 않습니다'오류를 복제 할 수 없습니다. - 이해가 안됩니다.

최근에 별도의 스레드에서 WinForms 컨트롤과 상호 작용할 때 'cross-thread operation not valid' issues을 처리 할 패턴을 설정했습니다.

이것을 단리하기 위해 단위 테스트를 설정하고 내 SynchronisationContext 확장이 문제를 해결했다는 것을 알았 기 때문에 하나의 버튼과 'PerformClick()'이라는 코드가있는 간단한 테스트 양식을 만들었습니다. '다른 스레드에서 문제를 복제하려면 :

[STAThread] 
    static void Main() 
    {   
     using (TestForm form = new TestForm()) 
     { 
      Thread t1 = new Thread(() => Application.Run(form)); 
      Thread t2 = new Thread(() => form.buttonStart.PerformClick()); 
      form.Activated += (sender, args) => t2.Start(); 
      t1.Start(); 
      Thread.Sleep(1000); //Prevents form from being disposed before 'click' can occur from other thread. 
     }      
    } 

테스트 폼은 문자 그대로 하나의 버튼이있는 빈 양식입니다. 이 코드를 실행했을 때 예상대로 크로스 스레드 연산 예외가 발생했습니다.

그러나 코드를 NUnit 테스트에 넣으면 예외가 발생하지 않습니다. 여기 내 단위 테스트는 다음과 같습니다

[Test] 
    public void PostToControl_AcrossThreads() 
    {   
     //Notes: This code normally generates a cross-thread exception. 
     //For some reason, when you run it in the scope of the unit test, the exception is not generated. 
     using (TestForm form = new TestForm()) 
     { 
      Thread t1 = new Thread(() => Application.Run(form)); 
      Thread t2 = new Thread(() => form.buttonStart.PerformClick()); 
      form.Activated += (sender, args) => t2.Start(); 
      t1.Start(); 
      Thread.Sleep(1000); //Prevents form from being disposed before 'click' can occur from other thread. 
     } 
    } 

은 내가이 발생하는 이유 명확한 몰랐다 것을 깨달았다, 그래서 누군가가 가르치 려 수

:-) 전문가에게 던지는거야? 양식 테스트를 네이티브 방식과 비교했을 때 단위 테스트에서 다른 점이 무엇입니까?

답변

2

이 동작은 속성에 의해 제어됩니다 : 기본적으로 Control.CheckForIllegalCrossThreadCalls

, 디버거 당신이보고있는 행동 인, 연결되어있는 경우에만 해당됩니다.

+0

크로스 스레딩 제어 액세스에서 예외가 발생합니다. 이것이 없으면 때로는 잘 작동하고 때로는 실패 할 것입니다 - 이것은 단순히 지속적으로 실패하게 만듭니다. – Basic

+0

완벽한! 이것은 훌륭한 정보입니다. 답변 해 주셔서 대단히 감사합니다. – Martaver

+1

@Martaver 첨부하여 테스트하는 동안 디버그하려고합니까? 예외가 생기고 있니? – Damith

3

PerformClick() 이외의 것을 사용하십시오. 예를 들어 form.buttonStart.Text = "This is my form"; 또는 위치 변경 등 ...

이유는 PerformClick() 메서드는 .NET 이벤트 Click 만 발생시키기 때문입니다. 그러나 크로스 스레드 작업의 문제는 windows-message-loop를 사용하는 것입니다. 따라서 "문제 해결"을 원하면 windows-message-loop를 사용하는 몇 가지 작업을 수행해야합니다.

+0

감사합니다. TcKs. 불행히도, 텍스트 값을 설정하고 단추의 위치를 ​​설정하고 크로스 스레드 예외를 표시하려고 시도하지 않았습니다. 내 원래 코드는 컨트롤에 액세스하여 오류를 생성 할 수 있기 때문에 문제가 컨트롤 작업과 관련이 있다고 생각하지 않습니다. – Martaver

0

누구든지 나를 계몽시킬 수 있습니까? 단위가 다르게 발생하는 이유는 무엇입니까? 테스트는 기본적으로 양식을 실행하는 것과 비교됩니다.

다른 것은 없습니다.

Nunit에서 예외를 확인해야하는 경우 Exception Asserts을 사용하는 것이 좋습니다. 그렇지 않으면 nunit이 예외를 표시하지 않습니다.

적어도 예외에 대한 자산을 수행하지 않는 경우 try catch 블록을 넣고 예외를 기록하면 테스트 케이스에서도 동일한 예외가 발생합니다.

+0

UnhandledException 고마워요,하지만 내 문제는 단위 테스트에서 동일한 코드를 실행할 때 예외가 처음에 생성되지 않는다는 것입니다. 나는 이것이 꽤 분명한 스레딩 문제라고 확신합니다. – Martaver

+0

@Martaver는 단위 테스트 중에 오류 로깅을 사용하여 확인합니까? 예외가 발생하는 곳을 확인하십시오. 나는 그것이 같은 선이라고 확신한다. – Damith

+0

자세히 살펴보면, 맞습니다 :) 그러나 디버그 모드에서만 예외가 발생합니다. 니콜라스 버틀러 (Nicholas Butler)의 답변에 따르면 디버거없이 단위 테스트를 실행할 때 동작이 표시되지 않는 이유가 설명되어 있습니다. – Martaver

관련 문제