0

Templated コントロールのスレッド同期に問題があります (AutoComplete コントロールを実行しようとしています)。

私のコントロール内には、次のコードがあります。

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) をコメント アウトすると、問題なく動作しますが、サービス コールが希望どおりに調整されません。

スロットルの部分だけコメントアウトしても何も起こりません。

4

2 に答える 2

1

Asti は正しい考えを持っていますが、はるかに優れたアプローチは、IScheduler代わりに Throttle に引数を提供することです。

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

これにより、SelectMany まで、UI スレッド (ShowProgressBar を含む) でその下の操作が行われます。

于 2012-09-22T21:37:55.950 に答える
1

すべての依存関係オブジェクトでは、依存関係プロパティへの変更は Dispatcher スレッドでのみ行う必要があります。はThrottle別のスケジューラを使用しているため、後続のコンビネータで UI を変更するとDo、アクセス例外が発生します。

これは次の方法で解決できます。

  1. Dispatcher に副作用を引き起こすアクションの前にObserveOnDispatcherを追加します。必要に応じて、パイプラインで別のスケジューラを使用します。
  2. Dispatcher.Invokeを使用して、ディスパッチャーを介して副作用を実行します。例えば、 .Do(() => Dispatcher.Invoke(new Action(ShowProgressBar)))
于 2012-09-22T20:38:24.057 に答える