2009-04-07 8 views
1

이 질문은 이전에 묻지 만 정확하게 묻지는 않았다고 생각합니다.다른 스레드에서 UI 업데이트

집중적 인 작업이 있으며 UI를 응답 성있게 유지하고 싶습니다. 백그라운드 작업자가 최선의 방법이라고 말하는 몇 가지 게시물을 읽었지만 집중적 인 작업에 대한 소스 코드가 있다고 가정합니다.

나는 소스 코드가없는 라이브러리가 있는데, 진행 상황을 확인할 수있는 유일한 방법은 해고 된 이벤트에 연결하여 정보를 얻을 수있는 방법입니다.

MSDN 사이트에서 본 예는 소스가 있다고 가정합니다.

이벤트에 연결하여 진행률 (백분율 값)을 얻는 방법을 알고 있지만 그 값을 UI로 다시 가져 오는 방법은 무엇입니까?

답변

2

다음 답변은 제 직감에 기반을두고 제 3 자 libs를 사용하여 실제로 테스트하지 않았습니다.

  • 평소와 같이 간단한 배경 (BackGroundWorker 아님) 스레드에서 호출하는 것처럼 타사 lib 코드를 호출하십시오.
  • 라이브러리 구성 요소의 이벤트를 코드의 일반 이벤트 처리기 (UI 업데이트 예정)에 연결합니다. 이벤트 처리기 코드에서
  • 은 다음과 같아야합니다

    private void EventHandler(object sender, DirtyEventArgs e) 
    { 
        if (myControl.InvokeRequired) 
         myControl.Invoke(new MethodInvoker(MethodToUpdateUI), e); 
        else 
         MethodToUpdateUI(e); 
    } 
    
    private void MethodToUpdateUI(object obj) 
    { 
        // Update UI 
    } 
    
+0

Invoke 메서드를 사용하면 메서드 이름을 전달할 수 있습니까? 아니면 위임자를 먼저 만들어야합니까? –

+0

변경 사항을 확인하십시오. MethodInvoker 대리자를 사용할 수 있습니다. 메서드 이름만으로는 충분하지 않습니다. – NileshChauhan

0

두 번째 스레드와 스레드 안전 큐를 사용하여 원하는 결과를 얻을 수 있습니다.

이벤트를 수신하는 두 번째 스레드를 만들 수 있습니다. 새 이벤트가 발생하면 이벤트 정보를 대기열에 푸시합니다 (스레드 안전 동기화 됨).

x 시간마다 큐를 검사하고 새 이벤트가있는 경우를 대비하여 타이머 (Windows.Forms.Timer)를 사용하면 UI를 업데이트 할 수 있습니다.

타이머가 주 스레드에서 실행되므로 안전하게 UI를 업데이트 할 수 있으며 가벼운 무게로 만들면 타이머가 오래 인식되어 차단되지 않습니다.

+0

@Vince을 - 아마도하지만 당신은 "컨트롤"에 대한 액세스 권한이없는 경우 메인 스레드에서 이벤트를 던져 그 유일한 방법 클래스를 생성하고 그냥 이벤트를 던지기위한 더미 객체를 만들고 싶지 않다면 –

0

유사한 논의가 this Q에있다. 어떤 이유로 든 BackgroundWorker를 사용할 수 없거나 사용하지 않으려는 경우 자체 스레드를 사용하고 이벤트를 UI 스레드로 마샬링 할 수 있습니다.

private void Initialise() {  
    MyLibClass myLibClass = new MyLibClass(); 
    myLibClass.SomeEvent += SomeEventHandler; 
    ThreadPool.QueueUserWorkItem(myLibClass.StartLongTask); 
} 


private void SomeEventHandler(EventArgs e) {  
    if (this.Dispatcher.Thread != Thread.CurrentThread) { 
     this.Dispatcher.Invoke(delegate { DoStuffOnUIThread(e); }); 
    } 
    else {   
     DoStuffOnUIThread(e);  
    } 
} 
관련 문제