我需要一些关于Rx行为的解释

时间:2013-05-19 13:35:54

标签: c# .net system.reactive

当我使用带有linq过滤器的Reactive Extensions(Rx)时会发生什么?

是吗,

var move = Observable.FromEventPattern<MouseEventArgs>(frm, "MouseMove");
IObservable<System.Drawing.Point> points = from evt in move
                                           select evt.EventArgs.Location;
var overfirstbisector = from pos in points
                        where pos.X == pos.Y 
                        select pos;
var movesub = overfirstbisector.Subscribe(pos => Console.WriteLine("mouse at " + pos));
从这个效率更高效?

private void MouseMove(object sender, EventArgs args)
{
  if (args.Location.X == args.LocationY)
    Console.WriteLine("mouse at " + args.Location);
}

我不谈论过滤逻辑本身,而是谈论方法的事件行为。 在Rx中,事件的提升方式与常规事件完全相同,但是使用了warapper或引擎盖下有什么特别之处?

3 个答案:

答案 0 :(得分:1)

Rx查询并不比直接订阅事件更有效。在引擎盖下,Rx查询仍然订阅事件并添加一些逻辑(例如,对于调度程序),所以我会说你正在交易一点性能以提高可读性和灵活性(因为你可以快速改变和适应查询)和可测试性(因为Rx查询可以更容易地进行单元测试)。

答案 1 :(得分:1)

在这种情况下,在典型的事件处理程序中使用Rx查询没有算法性能优势 - 事实上,您的Rx查询实际上可能比典型的事件处理程序略慢。 “引擎盖下”Rx查询基本上与典型的事件处理程序做同样的事情,但是以更清洁的方式。

答案 2 :(得分:1)

Rx没有什么“特别”。 Rx只是一个库,而不是语言功能。如果你愿意的话,你可以在一个普通的旧C#项目中自己构建Rx,就好像微软的聪明人首先想到的那样。代码是开源的,所以你可以下载它,看看它是如何工作的(不可否认它在v2中变得更加复杂)

在您的示例中,Rx代码需要执行以下操作:

  1. frm对象
  2. 上反复查找名为“MouseMove”的事件
  3. 从事件
  4. 创建可观察序列(IObservable<MouseEventArgs>
  5. 确保隐式IObservable合约的安全语义,例如这些值是顺序的,订阅是线程安全的等等。
  6. 执行条件检查
  7. 订阅序列(安全)
  8. 按下值时打印到控制台。
  9. 相反,非rx代码执行以下操作:

    1. 从基类接收虚拟来电
    2. 执行条件检查
    3. 将值打印到控制台。
    4. 所以没有反思&amp;没有安全检查,但结果相同。在实践中,两者的性能都非常快,因此您不太可能看到任何性能差异。

      关于单元测试,我认为支持或反对的任何论据都是无稽之谈。我们正在讨论MouseMove事件,你打算如何进行单元测试呢?把所有Rx放在你的代码库中似乎并不代表我自己的代价(更慢,更多代码,另一个开发理解框架等等)。