-1

当我将 Reactive Extensions (Rx) 与 linq 过滤器一起使用时,幕后会发生什么?

这是,

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 或者引擎盖下有什么特别的东西?

4

3 回答 3

1

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

于 2013-05-19T21:50:42.993 回答
1

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

于 2013-05-19T21:57:56.350 回答
1

Rx 没有什么“特别”的地方。Rx 只是一个库,而不是语言功能。如果你愿意,你可以在一个普通的旧 C# 项目中自己构建 Rx,只是碰巧微软的聪明人首先想到了它。该代码现在是开源的,因此您可以下载它并查看它是如何工作的(诚然,它在 v2 中变得更加复杂)

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

  1. frm反射性地在对象上查找名为“MouseMove”的事件
  2. IObservable<MouseEventArgs>从事件中创建一个可观察序列 ( )
  3. 确保隐式 IObservable 合约的安全语义,例如值是顺序的、订阅是线程安全的等。
  4. 进行条件检查
  5. 订阅序列(安全)
  6. 推送值时打印到控制台。

相反,非 rx 代码执行以下操作:

  1. 从基类接收虚拟调用
  2. 做条件检查
  3. 将值打印到控制台。

所以没有反射和安全检查,但结果相同。实际上,两者的性能都非常快,因此您不太可能看到任何性能差异。

关于单元测试,我认为任何支持或反对的论点都是无稽之谈。我们正在讨论 MouseMove 事件,您将如何对其进行单元测试?在我看来,将所有的 Rx 放在你的代码库中似乎不会为自己付出代价(更慢、更多的代码、另一个让开发人员理解的框架等......)

于 2013-05-29T11:52:43.153 回答