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的情况下也可以正常工作。