2012-09-22 3 views
0

나는이 코드가 내 컨트롤 내부RX 스로틀

(A 자동 완성 컨트롤을하려고) 내 템플릿 기반 컨트롤에서 스레드 동기화 몇 가지 문제가 있습니다

protected override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 

     var searchTextBox = GetTemplateChild("SearchTextBox") as TextBox; 
     if (searchTextBox != null) 
     { 
      var searchDelegate = SearchAsync; 

      Observable.FromEventPattern(searchTextBox, "TextChanged") 
       .Select(keyup => searchTextBox.Text) 
       .Where(TextIsLongEnough) 
       .Throttle(TimeSpan.FromMilliseconds(500)) 
       .Do(ShowProgressBar) 
       .SelectMany(searchDelegate) 
       .ObserveOn(Dispatcher) 
       .Subscribe(async results => await RunOnDispatcher(() => 
                     { 
                      IsInProgress = false; 
                      SearchResults.Clear(); 
                      foreach (var result in results) 
                      { 
                       SearchResults.Add(result); 
                      } 
                     })); 
     } 
    } 

을 그리고 그것은 불평 내 ShowProgressBar 메서드 내에서 다른 스레드에 의해 마샬링 된 코드에 액세스하려고합니다.

Throttle과 ObserveOn (Dispatcher)을 주석 처리하면 정상적으로 작동하지만 원하는대로 내 서비스 호출을 차단하지 않습니다.

스로틀 부분 만 주석 처리하면 아무 일도 일어나지 않습니다.

+0

나는 RX 2.0 베타를 사용하고있다. – David

+0

이것은 대답이 아니지만 빠른 주석이다 - 나는 당신이 당신의 코드에서'async' /'await'을 필요로하지 않는다고 생각한다. Rx가 효과적으로 당신을 기다리고 있습니다. 하지 않고 그것을 시도하고 여전히 잘 작동하는지 알려주십시오. – Enigmativity

+0

True Enigmativity - 코드가 비동기/작동하지 않고 작동합니다. – David

답변

1

아 스티의 .Do(() => Dispatcher.Invoke(new Action(ShowProgressBar))) 오른쪽 아이디어를 얻었으나, 훨씬 더 좋은 방법은 대신 스로틀 링하는 IScheduler 인수를 제공하는 것 ShowMenu까지 ShowProgressBar를 포함하여).

+0

이것은 문제를 해결했습니다! 내가 사용한 구문은 .Throttle (TimeSpan.FromMilliseconds (500), CoreDispatcherScheduler.Default)입니다. – David

1

모든 종속성 개체에는 종속성 속성이 변경되면 be made only on the Dispatcher thread이 필요합니다. Throttle은 다른 스케줄러를 사용하므로 이후의 Do 연결자에서 UI를 변경하면 액세스 예외가 발생합니다.

다음과 같은 방법으로이 문제를 해결할 수 있습니다

  1. 는 Dispatcher에서 부작용을 일으킬 조치 전에 ObserveOnDispatcher를 추가합니다. 선택적으로 파이프 라인을 따라 다른 스케줄러를 사용하십시오.
  2. Dispatcher.Invoke을 사용하여 디스패처를 통해 부작용을 실행합니다. (가 UI 스레드에서 발생 아래

    // NB: Too lazy to look up real name 
    .Throttle(TimeSpan.FromMilliseconds(500), CoreDispatcherScheduler.Instance) 
    

    이 작업을 할 것입니다 : 예,

+0

안녕하세요, 음, Do (ShowProgressBar) 호출 전에 ObserveOnDispatcher()를 추가하면 ShowProgressBar가 호출되지 않습니다. Win8에서 디스패처는 CoreDispatcher이며 위에 나온 코드에서 사용하는 .RunAsync()를 사용합니다. 내 문제는 해당 호출 전에 ObserveOnDispatcher() 사용하면 코드를 호출 할 절대로 것입니다. – David