2010-01-29 5 views
11

별도의 스레드에서 자체 이벤트 디스패처를 실행하는 프레임 워크를 사용하고 있습니다. 프레임 워크는 일부 이벤트를 생성 할 수 있습니다.C#의 스레드 간 이벤트 처리

class SomeDataSource { 

    public event OnFrameworkEvent; 

    void FrameworkCallback() { 

     // This function runs on framework's thread. 

     if (OnFrameworkEvent != null) 
      OnFrameworkEvent(args); 
    } 
} 

이러한 이벤트를 Winforms 스레드의 Winforms 개체에 전달하려고합니다. 나는 분명히 InvokeRequired를 확인하고 필요한 경우 Winforms 스레드로 전달합니다.

class SomeForm : Form { 

    // ... 

    public void SomeAction(SomeArgs args) { 
     if (InvokeRequired) { 
      BeginInvoke(new Action(SomeAction), args); 
      return; 
     } 

     // ... 
    } 

} 

이제 이벤트는 폼이 모든 종류의 문제가 발생하는 폐쇄되는 과정에있을 때 배달, 그래서 같이 윈폼 스레드에서 프레임 워크의 이벤트 소스에서 폼의 이벤트 핸들러의 등록을 취소 할 수 있습니다

var form = new SomeForm(); 
var src = new SomeDataSource(); 

// ... 

src.OnFrameworkEvent += form.SomeAction; 
form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction; 
  1. 이제 이 스레드 접근 방식입니까? 양식이 닫히는 중이고 외부 스레드가 BeginInvoke을 호출하는 경우 양식을 닫으면 호출이 실행 대기 상태로 유지됩니까? (이는 여전히 동일한 문제가 발생할 가능성이 있음을 의미 함)

  2. 크로스 스레드 이벤트 처리에 더 나은 접근법이나 권장 패턴이 있습니까?

답변

4

아니오 그렇지 않습니다. 스레드는 등록을 취소하고 양식을 닫을 때 이벤트 처리기를 실행 중일 수 있습니다. 적은 확률이지만 0은 아닙니다. 양식을 닫기 전에 스레드를 정지시켜야합니다. 중단하고 싶지 않으면 FormClosing 이벤트를 취소하여 양식을 열린 상태로 유지 한 다음 스레드의 완료 콜백을 닫습니다.

자세한 내용은 this thread을 확인하십시오.

+0

나는이 접근법을 좋아한다. 나는 스레드가 완료되었을 때 시그널링을 위해 콜백 메소드를 사용하는 것을 좋아한다. –

1

고유 한 이벤트 디스패처와 함께 프레임 워크를 사용하지 않았지만 작성한 스레드에 대한 경험이 있습니다. 내 경험은 다음과 같습니다

  1. 이 접근법은 스레드로부터 안전하지 않습니다. 프로그램 자체가 닫히더라도 호출은 여전히 ​​호출됩니다. 작업 관리자 (프로그램이 닫힌 후에 스레드가 매달려 있음)에서 이것을 보았습니다. (작업 관리자에서 프로그램을 종료하더라도). 나는 그 스레드를 나중에 별도로 죽여야 만했다.

  2. 양식을 닫을 때 디스패처 스레드를 죽여야 스레드에 문제가 발생해도 응답하지 않습니다.

    form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction; 
    // pseudo-code (find c# equivalent) 
    if (dispatcherthread.isrunning) 
    dispatcherThread.kill(); 
    
+0

다른 Winforms를 처리하기 위해 디스패처 스레드가 살아 있어야하는 경우 어떻게해야합니까? –

+0

나는 그것이 두려워합니다. 동일한 양식 소스를 수신하는 여러 양식이 있습니다. –

+0

내가 무슨 말을하는지 정확히 이해하면 스레드의 IsBackground 속성을 true로 설정하면 스레드가 걸리지 않습니다. –

2

이 코드를 생성자 CheckForIllegalCrossThreadCalls = false;에 추가 할 수 있으며 예외는 발생하지 않습니다.