×

Loading...

聊聊Rective Extention(Rx)

本文发表在 rolia.net 枫下论坛聊聊Rective Extention(Rx)
Rx的出现也是为了简化异步编程,但是初学者会发现至少从写法来看,Rx好像并没有减少多少代码量,这也确实是事实。俺的理解是,Rx的出现所带来的最大好处是使得异步编程LINQ化,也就是说,程序员可以用LINQ语法来操作一系列的异步事件,这个好处是巨大的,LINQ的出现使得以前成百上千行代码变得只是弹指一挥间。这也是为什么在网上一提到Rx,总是会跟着Linq
举个例子,比如,一个WPF Program,一个鼠标在屏幕上乱画,我想在这个鼠标的X坐标超出100的时候在屏幕上显示这个坐标,小于100则不显示,用普通的Event方法:
private void Form1_Load(object sender, EventArgs e)
{
this.MouseMove += (s, args) =>
{
if(args.Location.X > 100)
this.label1.Text = args.Location.ToString();
};
}

用Rx:
private void Form1_Load(object sender, EventArgs e)
{
Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
.Where(s => s.EventArgs.X > 100)
.Subscribe(s => this.label1.Text = s.EventArgs.Location.ToString());
}

可以看出Rx把鼠标的”MouseMove”事件当作一连串Events Collection发送出来,然后由一个Where(.. 进行过滤,只把X > 100的Event继续向下发送,最终到了Subscribe(.. 这些Event算是到头了,开始由里面的函数进行实际的处理。逻辑很清晰,虽然写法上不见的比传统的例子省多少代码,但这只是因为我的例子太过渺小,如果其中逻辑比较复杂,能看出Rx的写法会更有效率,也更清晰,便于维护

现在,把这个例子变得复杂一些吧,我想在鼠标停止0.5秒之后再更新label1.Text的内容,而不是每时每刻的更新,用Rx的话:

Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
.Where(s => s.EventArgs.X > 100)
.Throttle(TimeSpan.FromSeconds(0.5))
.ObserveOn(this)
.Subscribe(s => this.label1.Text = s.EventArgs.Location.ToString());
就加了2行
.Throttle(TimeSpan.FromSeconds(0.5)) // 用于让系统等待0.5秒,如果这0.5秒之内没有新的MouseMove event coming,则把当前的Event往下传递到 .ObserveOnDispatcher()
.ObserveOn(this) // 是必须的,因为又一次涉及到跨线程操作

同样的功能如果由传统的Event操作来写,不知道要复杂多少,至少要用到一个Timer,还要监测Timer.Internvel event,太可怕了

继续,让事情变得更复杂一些,我想在每次鼠标每停留2次(或者n次,无所谓)以上的时候显示这n次分别停留了哪几个坐标点?

Rx程序如下:
Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
.Where(s => s.EventArgs.X > 100)
.Throttle(TimeSpan.FromSeconds(0.5))
.Buffer(2)
.ObserveOn(this)
.Subscribe(s => this.label1.Text = s.Select(x => x.EventArgs.Location.ToString()).Aggregate((a, b) => a + ", " + b));

这功能如果用传统方法写….算了,想也不愿意去想



Rx这个东西,对初学者有些晦涩,类似于理解async await之前需要先了解Task。Rx的核心是两个Interface
IObservable<T>
IObserver<T>


吃饭… 回来再写更多精彩文章及讨论,请光临枫下论坛 rolia.net
Sign in and Reply Report

Replies, comments and Discussions:

  • 工作学习 / 科技领域杂谈 / 聊聊Rective Extention(Rx)
    本文发表在 rolia.net 枫下论坛聊聊Rective Extention(Rx)
    Rx的出现也是为了简化异步编程,但是初学者会发现至少从写法来看,Rx好像并没有减少多少代码量,这也确实是事实。俺的理解是,Rx的出现所带来的最大好处是使得异步编程LINQ化,也就是说,程序员可以用LINQ语法来操作一系列的异步事件,这个好处是巨大的,LINQ的出现使得以前成百上千行代码变得只是弹指一挥间。这也是为什么在网上一提到Rx,总是会跟着Linq
    举个例子,比如,一个WPF Program,一个鼠标在屏幕上乱画,我想在这个鼠标的X坐标超出100的时候在屏幕上显示这个坐标,小于100则不显示,用普通的Event方法:
    private void Form1_Load(object sender, EventArgs e)
    {
    this.MouseMove += (s, args) =>
    {
    if(args.Location.X > 100)
    this.label1.Text = args.Location.ToString();
    };
    }

    用Rx:
    private void Form1_Load(object sender, EventArgs e)
    {
    Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
    .Where(s => s.EventArgs.X > 100)
    .Subscribe(s => this.label1.Text = s.EventArgs.Location.ToString());
    }

    可以看出Rx把鼠标的”MouseMove”事件当作一连串Events Collection发送出来,然后由一个Where(.. 进行过滤,只把X > 100的Event继续向下发送,最终到了Subscribe(.. 这些Event算是到头了,开始由里面的函数进行实际的处理。逻辑很清晰,虽然写法上不见的比传统的例子省多少代码,但这只是因为我的例子太过渺小,如果其中逻辑比较复杂,能看出Rx的写法会更有效率,也更清晰,便于维护

    现在,把这个例子变得复杂一些吧,我想在鼠标停止0.5秒之后再更新label1.Text的内容,而不是每时每刻的更新,用Rx的话:

    Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
    .Where(s => s.EventArgs.X > 100)
    .Throttle(TimeSpan.FromSeconds(0.5))
    .ObserveOn(this)
    .Subscribe(s => this.label1.Text = s.EventArgs.Location.ToString());
    就加了2行
    .Throttle(TimeSpan.FromSeconds(0.5)) // 用于让系统等待0.5秒,如果这0.5秒之内没有新的MouseMove event coming,则把当前的Event往下传递到 .ObserveOnDispatcher()
    .ObserveOn(this) // 是必须的,因为又一次涉及到跨线程操作

    同样的功能如果由传统的Event操作来写,不知道要复杂多少,至少要用到一个Timer,还要监测Timer.Internvel event,太可怕了

    继续,让事情变得更复杂一些,我想在每次鼠标每停留2次(或者n次,无所谓)以上的时候显示这n次分别停留了哪几个坐标点?

    Rx程序如下:
    Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
    .Where(s => s.EventArgs.X > 100)
    .Throttle(TimeSpan.FromSeconds(0.5))
    .Buffer(2)
    .ObserveOn(this)
    .Subscribe(s => this.label1.Text = s.Select(x => x.EventArgs.Location.ToString()).Aggregate((a, b) => a + ", " + b));

    这功能如果用传统方法写….算了,想也不愿意去想



    Rx这个东西,对初学者有些晦涩,类似于理解async await之前需要先了解Task。Rx的核心是两个Interface
    IObservable<T>
    IObserver<T>


    吃饭… 回来再写更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • 我还是原来的观点。是好东东,但有点生不逢时。
      此技术用在 Smart phone 或 EDA 会很好。但MS 的smart phone 市场太小。EDA 还停在Windows Mobile 6.5/.NET 3.5。
      • 嗯,也是,目前我用Rx最多的地方就是Win Phone的UI操作,还有就是对Sensor的操作,比如GPS坐标是否进入了某一个特定区域、手机左右摇晃的判断等等,Rx对代码的简化是很可观的。不过Rx是很Generic的一种技术,商业开发迟早会认识到它的价值,再等几年吧
      • Rx现在的缺点是版本有些混乱,而且仍然在“快速”的进化,1年前的代码放到现在不一定能用,现在的代码一年之后也不一定能用。Silverlight,Windows 8,WPF,Windows Phone之间的代码并不100%兼容