axb*_*eit 0 c# asynchronous task async-await uwp
我有一个带有PDFReader的UWP应用。PDFReader有一个搜索窗口。在搜索文本框中输入单词后,便可以开始搜索。当前,这样一来,如果您开始搜索,则必须等待3秒钟,直到看到一条消息,该单词的出现频率很高。
现在,我想用“正在搜索...”消息填充这3秒钟。
我有一个解决方案是:
private async void DoSearch(...)
{
//...
Task<string> searchingText = setSearchMsg();
infoBox.Text = await searchingText;
//...
}
private async Task<string> setSearchMsg()
{
infoBox.Text = "Searching...";
await Task.Delay(1);
return "";
}
Run Code Online (Sandbox Code Playgroud)
但这看起来并不正确。我注意到的一件事是,当我正在寻找一个单词并且可以在80页中找到3000次该单词时,infoBox跳过“正在搜索...”消息,并再次将信息框填充为空。为了解决这个问题,我可以将更Task.Delay改为like Task.Delay(100),这并不是我认为正确的解决方案。
您应该使用Microsoft的Reactive Framework(aka Rx)-NuGet System.Reactive.Windows.Threading并添加using System.Reactive; using System.Reactive.Linq;-然后您可以做一些令人惊奇的事情。
我模拟了一些类似于您的代码。我从TextBox和TextBlock和一个用于执行搜索的虚拟方法开始:
private async Task<string> PerformSearchAsync(string text)
{
await Task.Delay(TimeSpan.FromSeconds(2.0));
return "Hello " + text;
}
Run Code Online (Sandbox Code Playgroud)
现在,在构造函数中,this.InitializeComponent();我创建了以下可观察到的对象,以响应TextChanged我的所有事件textBox1:
IObservable<EventPattern<TextChangedEventArgs>> textChanges =
Observable
.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
h => textBox1.TextChanged += h,
h => textBox1.TextChanged -= h);
Run Code Online (Sandbox Code Playgroud)
然后我写了一个查询来响应文本更改:
IObservable<string> query =
textChanges
.Select(x =>
Observable
.FromAsync(() => PerformSearchAsync(textBox1.Text))
.StartWith("Searching..."))
.Switch();
Run Code Online (Sandbox Code Playgroud)
这实际上是在等待每个文本更改并启动异步调用PerformSearchAsync-这将以字符串形式返回搜索结果-并且还将立即返回该字符串"Searching..."。将.Switch()用于确保只有最新的呼叫PerformSearchAsync实际返回的结果。
现在,我可以简单地观察查询:
_subscription =
query
.ObserveOnDispatcher()
.Subscribe(x => textBlock1.Text = x);
Run Code Online (Sandbox Code Playgroud)
变量_subscription定义为private IDisposable _subscription = null;。它用于使我可以调用_subscription.Dispose()以安全地关闭订阅。
它表现出您想要的方式。
我的整个代码如下所示:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace App5
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private IDisposable _subscription = null;
public MainPage()
{
this.InitializeComponent();
IObservable<EventPattern<TextChangedEventArgs>> textChanges =
Observable
.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
h => textBox1.TextChanged += h,
h => textBox1.TextChanged -= h);
IObservable<string> query =
textChanges
.Select(x =>
Observable
.FromAsync(() => PerformSearchAsync(textBox1.Text))
.StartWith("Searching..."))
.Switch();
_subscription =
query
.ObserveOnDispatcher()
.Subscribe(x => textBlock1.Text = x);
}
private async Task<string> PerformSearchAsync(string text)
{
await Task.Delay(TimeSpan.FromSeconds(2.0));
return "Hello " + text;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您应该能够对此进行调整以使其与代码一起使用。
| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |