使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
我之前有一篇文章介绍到了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");
}
}
}
运行起来可以看到如下的效果

传统的方案
针对这样的一种需求,我们按照传统的思路该如何实现呢?说实在的,很难做到。这里面有一个比较复杂的逻辑,也就是说,当一个事件发生了,我们不能马上处理,而是要等待一点时间看看(例如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");
}));
} }
}
注意,我们在这里用了一个Throttle的方法,它可以设置一个时间间隔,在这个时间间隔里面发生的事件,应该只处理一次(最后一个为准),所以运行起来看的效果如下

这里显示的结果取决于你输入的速度。
值得一提的是,在WPF中如果应用双向绑定的技术,结合MVVM来做开发的话,对于此类事情的处理,可能会有一个简单的做法(不需要用到额外的组件),这是由于在WPF 4.5中,对于绑定数据的更新,有多了一个选项:Delay
有兴趣的朋友可以参考http://msdn.microsoft.com/zh-cn/library/vstudio/system.windows.data.bindingbase.delay.aspx
使用Reactive Extensions(Rx),对短时间内多次发生的事件限流的更多相关文章
- 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
我之前有一篇文章介绍到了Reactive Extension这个组件,请参考下面的文章,其中有一些基本的概念和相关的链接 牛刀小试:使用Reactive Extensions(Rx),一行代码实现多线 ...
- Reactive Extensions(Rx) 学习
Bruce Eckel(著有多部编程书籍)和Jonas Boner(Akka的缔造者和Typesafe的CTO)发表了“反应性宣言”,在其中尝试着定义什么是反应性应用. 这样的应用应该能够: 对事件做 ...
- Reactive Extensions (Rx) 入门(5) —— Rx的事件编程
译文:https://blog.csdn.net/fangxing80/article/details/7749907 原文:http://www.atmarkit.co.jp/fdotnet/int ...
- Reactive Extensions (Rx) 入门(4) —— Rx的事件编程
译文:https://blog.csdn.net/fangxing80/article/details/7685393 原文:http://www.atmarkit.co.jp/fdotnet/int ...
- Reactive Extensions (Rx) 入门(3) —— Rx的事件编程
译文:https://blog.csdn.net/fangxing80/article/details/7628322 原文:http://www.atmarkit.co.jp/fdotnet/int ...
- Reactive Extensions (Rx) 入门(2) —— 安装 Reactive Extensions
译文:https://blog.csdn.net/fangxing80/article/details/7581937 原文:http://www.atmarkit.co.jp/fdotnet/int ...
- Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要
译文:https://blog.csdn.net/fangxing80/article/details/7381619 原文:http://www.atmarkit.co.jp/fdotnet/int ...
- Reactive Extensions(Rx)并发浅析
Reactive Extensions(Rx)并发浅析 iSun Design & Code .Net并行编程 - Reactive Extensions(Rx)并发浅析 关于Reactive ...
- .Net并行编程 - Reactive Extensions(Rx)并发浅析
关于Reactive Extensions(Rx) 关于Reactive Extensions(Rx),先来看一下来自微软的官方描述: The Reactive Extensions (Rx) is ...
随机推荐
- DirectX11 学习笔记2 - 加入关键事件 实现视角转换 旋转
上的程序的的基础上.在基类D3DBase添加摄像头功能 //录影机 void D3DBase::setCamera() { //关键事件 //假定A,S,D,W,Q,E,Z,X,C键被按下.动摄像机 ...
- MySQL引擎的相关知识
MySQL数 据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎,就必须重新编译MYSQL.在缺省情况下,MYSQL支持三个引 擎:ISAM.MYISAM和HEAP.另外两种类型I ...
- javascript中三目运算符和if else有什么区别
javascript中三目运算符和if else有什么区别今天写了一个图片轮播的小demo,用到了判断先试了一下if else,代码如下:if(n >= count-1){n =0;}else{ ...
- Nancy学习
Nancy学习 一.认识Nancy 今天听讲关于Nancy框架的培训,被Nancy的易用性所吸引.故晚上回来梳理了一下知识. 什么是Nancy呢?如标题所述,Nancy是一个轻量级的独立的框架: Na ...
- leetcode第33题--Search for a Range
Given a sorted array of integers, find the starting and ending position of a given target value. You ...
- HTML5表单提示placeholder属性兼容IE
placeholder 属性提供可描述输入字段预期值的提示信息(hint). 该提示会在输入字段为空时显示,并会在字段获得焦点时消失. 注释:placeholder 属性适用于以下的 <inpu ...
- JSFIDDLE 动力 Threejs
功能探秘
JSFIDDLE 助力 WebGL 功能探秘 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协 ...
- 华为JAVA(面试问题及答案节)
华为JAVA面试题 (后记:我没想到华为面试题是不寻常,,至少对我这种鸟来说是这样.对我个人来说.看看这样的题.可能比看<Think In Java>都还要好.因为这里面有很多的东西,都是 ...
- Linux--安装过程中的根文件系统的分析
前言: 在这篇文章中S3C6410公版的Linux BSP和U-Boot为了分析,名词和数据文件的所有内容本文是基于环境为例,所有的代码是在设置的示例进行分析的过程中.哈. 假设有不对或者不完好的地方 ...
- Repository 仓储
Repository 仓储 写在前面 首先,本篇博文主要包含两个主题: 领域服务中使用仓储 SELECT 某某某(有点晕?请看下面.) 上一篇:Repository 仓储,你的归宿究竟在哪?(二)-这 ...