2014-01-27 4 views
1

이 코드에 메시지를 전달하는 관찰 가능한 타이머를 필요 :는 UI 스레드에서 호출 UI 스레드

public void ShowProgress(Action<long> notify, Action terminate) 
{ 
    this.Progress = Observable.Timer(ProgressInterval, ProgressInterval).Finally(terminate).Subscribe(notify); 
} 

블록 UI 스레드 완전히는 응답 만들기 : ShowProgress가하는

Jobs.Current.ShowProgress(_ => 
    { 
     if (Jobs.Current.Duration == 0 && this.progressBarMarkJob.Value >= this.progressBarMarkJob.Maximum - this.progressBarMarkJob.Step/2) 
     { 
      this.progressBarMarkJob.Step /= 2; 
     } 
     this.progressBarMarkJob.PerformStep(); 
    },() => 
    { 
     stopwatch.Stop(); 
     var elapsed = string.Format(stopwatch.Elapsed.TotalHours >= 1 ? @"{0:hh\:mm\:SS}" : @"{0:mm\:SS}", stopwatch.Elapsed); 
     this.labelMarkTime.Text = string.Format("Elapsed{0:8}", elapsed); 
     this.labelMarkTime.Visible = true; 
     Jobs.Current.Duration = (uint)stopwatch.Elapsed.TotalSeconds; 
     this.progressBarMarkJob.Value = this.progressBarMarkJob.Maximum; 
    }); 

.

Subscribe() 호출 전에 .SubscribeOn (Scheduler.CurrentThread)을 삽입하면 더 이상 UI 스레드가 차단되지 않습니다. 그러나 메시지가 올바른 스레드의 UI로 전달되지 않기 때문에 교차 스레드 예외가 발생합니다.

타이머에서 업데이트를 가져올 수 있도록 UI가 응답하도록 - UI 스레드에 다시 게시되도록 작업 할 수있는 방법이 있습니까?

+0

분명히 UI와 다른 스레드에 가입 한 다음 호출을 실행하여 진행률 표시 줄을 Dispatcher를 통해 UI 스레드로 업데이트하십시오. 필요한 모든 정보를 가지고 있습니다. 왜이 문제가 발생하는지 확신 할 수 없습니다. 배경 => UI 호출 무술은 언덕만큼 오래되었고 여기에 주제를 다루는 데 대한 많은 질문이 있습니다. – Will

+0

감사합니다. 윌, 고맙습니다.하지만 많은 검색 후에도 그 답변을 찾을 수는 없으며, 나에게 분명하지 않습니다. 어때? 특히 설명서에서 Dispatcher를 사용하라고 알려주지 만 코드를 작성할 때 컴파일러는 해당 옵션을 시도 할 때 오류를 표시합니다. – shipr

답변

2

ObserveOn()에 전화를 추가해야합니다. 당신이 패키지 RX-XAML을 nuget 사용하는 경우) (ObserveOnDispatcher을 활용할 수 있습니다

this.Progress = Observable.Interval(ProgressInterval) 
          .ObserveOnDispatcher() 
          .Finally(terminate) 
          .Subscribe(notify); 

See my answer here to understand the difference between ObserveOn and SubscribeOn합니다. 또한 PerformStep()에 대한 코드를 제공하지 않습니다. 빠른 속도 및/또는 비 차단 기능이 있기를 바랍니다.

또한 TimerInterval으로 바꾸 었으므로 인수가 저장됩니다.

마지막으로 작업 완료시 구독 핸들 (this.Progress)을 삭제할 계획입니까?

+0

Thanks, @James, 매우 도움이됩니다. 특히 SubscribeOn과 ObserveOn의 대비입니다. 나는 Interval을 사용하는 것을 좋아한다. PerformStep 코드는 ProgressBar에서 제공하는 코드입니다. 예, 저는 작업이 완료되면 다른 곳에서 타이머를 폐기합니다. 그러나 이제는 오류가 발생합니다. 파일 또는 어셈블리 'System.Reactive.Core, Version = 2.0.20823.0, Culture = neutral, PublicKeyToken = f300afd708cefcd3'또는 해당 종속성 중 하나를로드 할 수 없습니다. 찾은 어셈블리의 매니페스트 정의가 어셈블리 참조와 일치하지 않습니다. (Exception from HRESULT : 0x80131040) – shipr

+0

호환되지 않는 버전의 Rx dll을 믹싱하는 것처럼 들립니다. 솔루션의 다른 곳에서 Reactive.Core에 대한 버전 별 참조를 만드나요? 최신 버전은 2.2입니다. –

+0

예, 저는 Reactive.Windows.Forms의 구형 버전을 참조하고있었습니다. 결정된! 다시 한번 감사드립니다. 모두 일하고있어. – shipr

관련 문제