Windows runtime WinRT TemplatedControl上的RX油门

Windows runtime WinRT TemplatedControl上的RX油门,windows-runtime,system.reactive,winrt-xaml,winrt-async,Windows Runtime,System.reactive,Winrt Xaml,Winrt Async,我的模板控件中的线程同步有一些问题(尝试执行自动完成控件) 在我的控制范围内,我有以下代码: protected override void OnApplyTemplate() { base.OnApplyTemplate(); var searchTextBox = GetTemplateChild("SearchTextBox") as TextBox; if (searchTextBox != null) {

我的模板控件中的线程同步有一些问题(尝试执行自动完成控件)

在我的控制范围内,我有以下代码:

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方法中,我试图访问由另一个线程封送的代码

如果我注释掉节流阀和ObserveOn(Dispatcher),它工作得很好,但它不会像我希望的那样节流我的服务调用


如果我只注释掉节流部分,则什么也不会发生。

每个依赖项对象都需要对依赖项属性进行任何更改。
Throttle
正在使用不同的计划程序,因此在后续的
Do
组合器中对UI进行任何更改都将导致访问异常

您可以通过以下方式解决此问题:

  • 在对调度程序造成副作用的任何操作之前添加。(可选)使用管道中的另一个计划程序
  • 用于通过调度程序执行副作用。例如,
    .Do(()=>Dispatcher.Invoke(新操作(ShowProgressBar)))

  • Asti的想法是正确的,但更好的方法是提供
    IScheduler
    参数来代替Throttle:

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

    这将使其下面的操作发生在UI线程(包括ShowProgressBar)上,直到SelectMany。

    嗨,如果我在调用Do(ShowProgressBar)之前添加ObserveOnDispatcher(),ShowProgressBar将永远不会被调用。在Win8中,dispatcher是一个CoreDispatcher,并使用.RunAsync(),我在上面的代码中确实使用了它。我的问题是,如果我在调用之前使用了ObserveOnDispatcher(),代码永远不会被调用。这确实解决了问题!我使用的语法是.Throttle(TimeSpan.frommilluses(500),CoreDispatcherScheduler.Default)。这不是答案,而是一个快速注释-我认为代码中不需要
    async
    /
    wait
    。Rx有效地完成了等待您的任务。请在不使用的情况下尝试,并让我知道它是否仍然可以正常工作。真正的谜-代码在不使用async/await的情况下也可以正常工作。