我之前有一篇文章介绍到了Reactive Extension这个组件,请参考下面的文章,其中有一些基本的概念和相关的链接

牛刀小试:使用Reactive Extensions(Rx),一行代码实现多线程任务执行规定时间后自动停止

Rx 目前还没有直接整合到.NET Framework 中,仍然是作为单独的组件存在。至于以后会不会,谁知道呢?我个人希望是可以整合进去。

不管怎么样,我今天还是以实例来讲解这个组件的使用,如果以后有更多有意思的场景,我也会用文章分享出来。

我们要解决的问题

在.NET应用程序开发期间,我们会大量地使用到事件,而且很多事件可能会不止一次地发生,例如TextChanged事件,KeyPress事件,MouseDown事件等等。

由于这些事件会多次发生,在某些场景下,如果每次都进行响应可能有负面的一些问题,例如性能问题。一个典型的案例是:假如我们需要根据TextChanged的事件去调用一个外部的服务,我们知道用户可以在一个很短的时间内(例如1秒内)快速输入很多的字符,同时还可能会删除字符,该事件会在每次发生更改的时候触发,如果按照传统的做法,每次都去调用服务,显然是不合适的,这样会有很多的服务请求。所以,我们可能希望,在某个时间范围内(例如1秒),只触发一次。

为了做这个演示,我做了如下的一个界面(WPF)

<Window x:Class="WpfApplicationSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<StackPanel>
<TextBox Name="txtInput"
TextChanged="txtInput_TextChanged"></TextBox> <RichTextBox Name="txtOutput"> </RichTextBox> </StackPanel>
</Window>

后台代码我简单地做了一个处理(我并没有真的去调用服务,而是做一个结果打印)

using System.Windows;
using System.Windows.Controls; namespace WpfApplicationSample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void txtInput_TextChanged(object sender, TextChangedEventArgs e)
{
txtOutput.AppendText(txtInput.Text+"\r");
}
}
}

运行起来可以看到如下的效果
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

传统的方案

针对这样的一种需求,我们按照传统的思路该如何实现呢?说实在的,很难做到。这里面有一个比较复杂的逻辑,也就是说,当一个事件发生了,我们不能马上处理,而是要等待一点时间看看(例如1秒),如果还有新的事件发生(可能会多个),则以1秒内最后那个事件为准。但是,这里还有一个例外情况,如果在1秒内没有其他事件发生,则这个唯一的事件就要被处理。

大家可以自己尝试想想看,要做到这样的逻辑判断实在不那么容易。

使用Rx的方案

而使用Rx的方案,则相对来说很简单,或者可以说是很直白。

首先,我们可以安装Reactive Extensions

然后,我们通过如下的方式来监听这个事件,而不是在xaml中直接定义。

using System;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls; namespace WpfApplicationSample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); Loaded += MainWindow_Loaded;
} void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Observable.FromEventPattern<TextChangedEventArgs>(this.txtInput, "TextChanged").Throttle(TimeSpan.FromSeconds(1)).Subscribe(x =>
this.Dispatcher.Invoke(() =>
{
txtOutput.AppendText(txtInput.Text + "\r");
}));
} }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

注意,我们在这里用了一个Throttle的方法,它可以设置一个时间间隔,在这个时间间隔里面发生的事件,应该只处理一次(最后一个为准),所以运行起来看的效果如下

这里显示的结果取决于你输入的速度。

值得一提的是,在WPF中如果应用双向绑定的技术,结合MVVM来做开发的话,对于此类事情的处理,可能会有一个简单的做法(不需要用到额外的组件),这是由于在WPF 4.5中,对于绑定数据的更新,有多了一个选项:Delay

有兴趣的朋友可以参考http://msdn.microsoft.com/zh-cn/library/vstudio/system.windows.data.bindingbase.delay.aspx

牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流的更多相关文章

  1. 使用Reactive Extensions(Rx),对短时间内多次发生的事件限流

    使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 我之前有一篇文章介绍到了R ...

  2. Reactive Extensions(Rx) 学习

    Bruce Eckel(著有多部编程书籍)和Jonas Boner(Akka的缔造者和Typesafe的CTO)发表了“反应性宣言”,在其中尝试着定义什么是反应性应用. 这样的应用应该能够: 对事件做 ...

  3. Reactive Extensions (Rx) 入门(5) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7749907 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  4. Reactive Extensions (Rx) 入门(4) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7685393 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  5. Reactive Extensions (Rx) 入门(3) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7628322 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  6. Reactive Extensions (Rx) 入门(2) —— 安装 Reactive Extensions

    译文:https://blog.csdn.net/fangxing80/article/details/7581937 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  7. Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要

    译文:https://blog.csdn.net/fangxing80/article/details/7381619 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  8. Reactive Extensions(Rx)并发浅析

    Reactive Extensions(Rx)并发浅析 iSun Design & Code .Net并行编程 - Reactive Extensions(Rx)并发浅析 关于Reactive ...

  9. .Net并行编程 - Reactive Extensions(Rx)并发浅析

    关于Reactive Extensions(Rx) 关于Reactive Extensions(Rx),先来看一下来自微软的官方描述: The Reactive Extensions (Rx) is ...

随机推荐

  1. 无鼠标Windows操作

    1.常用tab键,方便跳转 2.打开软件方式:  1.win+1,2,3...依序打开任务栏图标.常用软件可以放在这里: 2.创建quickStart文件夹,配置路径,将所有要用到的功能都放在这里.( ...

  2. 简单的OkHttp使用介绍

    Android系统提供了两种HTTP通信类,HttpURLConnection和HttpClient.关于HttpURLConnection和HttpClient的选择>>官方博客尽管Go ...

  3. 前台传参数时间类型不匹配:type 'java.lang.String' to required type 'java.util.Date' for property 'createDate'

    springMVC action接收参数: org.springframework.validation.BindException: org.springframework.validation.B ...

  4. 强类型DataSet的使用简明教程

    关于弱类型 DataSet的缺点: 无论何时从 DataSet检索值都是以Object类型返回,需要对它进行类型转换: 给其它开发者使用 时无法知道哪些列可用: 运行时才能知道所 有列名,数据绑定麻烦 ...

  5. 如何在MFC中创建非矩形button

    一般情况下,我们创建的按钮都是矩形的,但有时为了满足特殊的需求,我们要在对话框中创建一个非矩形的按钮,比如,圆形,椭圆等. 要实现一个非矩形的按钮,这就涉及到了自绘控件.自绘控件的方法有很多,可以参考 ...

  6. Ubuntu NFSserver 简易安装及使用

    服务器端(ip:192.168.1.100): sudo apt-get install nfs-kernel-server #安装nfs 客户端(ip:192.168.1.110): sudo ap ...

  7. Twitter全局唯一ID生成算法

    测试:private static void TestIdWorker() { HashSet<long> set = new HashSet<long>(); IdWorke ...

  8. 《C#图解教程》读书笔记之三:方法

    本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.方法那些事儿 (1)方法的结构:方法头—指定方法的特征,方法体—可执行代码的语句序列: (2)方法的调用:参 ...

  9. js中各种跨域问题实战小结(二)

    这里接上篇:js中各种跨域问题实战小结(一) 后面继续学习的过程中,对上面第一篇有稍作休整.下面继续第二部分: -->5.利用iframe和location.hash -->6.windo ...

  10. SQL Server 性能优化之——T-SQL 临时表、表变量、UNION

    这次看一下临时表,表变量和Union命令方面是否可以被优化呢? 阅读导航 一.临时表和表变量 二.本次的另一个重头戏UNION 命令 一.临时表和表变量 很多数据库开发者使用临时表和表变量将代码分解成 ...