2012-11-08 3 views
0

이벤트를 알리기 위해 콜백을 사용하는 라이브러리의 래퍼를 개발했습니다. 이 콜백은 UI의 스레드가 아닌 다른 스레드를 사용하여 호출되므로 래퍼는 다음 스크립트를 사용하여 이벤트 처리기를 WinForm 응용 프로그램의 올바른 스레드로 호출합니다. 오른쪽 스레드로 이벤트 디스패치

void AoComm::Utiles::Managed::DispatchEvent(Delegate^ ev, Object^ sender, Object^ args) 
{ 
ComponentModel::ISynchronizeInvoke^ si; 
array<Delegate^>^ handlers; 

if(ev != nullptr) 
{ 
    handlers= ev->GetInvocationList(); 

    for(int i = 0; i < handlers->Length; ++i) 
    { 
     // target implements ISynchronizeInvoke? 
     si = dynamic_cast<ComponentModel::ISynchronizeInvoke^>(handlers[i]->Target); 
     try{ 
      if(si != nullptr && si->InvokeRequired) 
      { 
       IAsyncResult^ res = si->BeginInvoke(handlers[i], gcnew array<Object^>{sender, args}); 
       si->EndInvoke(res); 

      }else{ 
       Delegate^ del = handlers[i]; 
       del->Method->Invoke(del->Target, gcnew array<Object^>{sender, args}); 
      } 
     }catch(System::Reflection::TargetException^ e){ 
      Exception^ innerException; 
      if (e->InnerException != nullptr) 
      { 
       innerException = e->InnerException; 

      }else{ 
       innerException = e; 
      } 
      Threading::ThreadStart^ savestack = (Threading::ThreadStart^) Delegate::CreateDelegate(Threading::ThreadStart::typeid, innerException, "InternalPreserveStackTrace", false, false); 
      if(savestack != nullptr) savestack(); 
      throw innerException;// -- now we can re-throw without trashing the stack 
     } 
    } 
    } 
} 

이 코드

꽤 잘 작동하지만, 나는 (물론, 등) 내 코드보다 동일한 작업을 수행 WPF에 대한 디스패처 클래스에 대해 읽었습니다. 그래서, 뭔가 (클래스, 메커니즘, ...) WinForms에 대한 Dispatcher 클래스에 상응합니까?

감사합니다.

답변

1

맞습니다. 올바른 방법이 아닙니다. Winforms 및 WPF에는 서로 다른 동기화 공급자가 있으며 System :: Threading :: SynchronizationContext :: Current에 해당 공급자가 설치됩니다.

사용하려면 생성자에서 Current 값을 복사하십시오. 이벤트를 준비 할 때 nullptr인지 확인하십시오. 그렇다면 작업자 스레드에서 객체가 생성되었고 직접 이벤트를 발생시켜야합니다. 그렇지 않은 경우 Post() 메서드를 사용하여 UI 스레드에서 도우미 메서드를 실행합니다. 도우미 메서드가 이벤트를 발생 시켰습니다.

+0

정보 주셔서 감사합니다. SynchronizationContext는 합리적인 방법 인 것 같습니다. – Jairo

관련 문제