3

查看Jeff Van Gogh 博客上的 Reactive Extensions for javascript 演示,我想我会在 C#/Winforms 中尝试一下,但它似乎不太好用。

我只是将它放入表单的构造函数中(安装并引用了 Rx 框架):

Observable.Context = SynchronizationContext.Current;
var mousemove = Observable.FromEvent<MouseEventArgs>(this, "MouseMove");
var message = "Time flies like an arrow".ToCharArray();

for(int i = 0; i < message.Length; i++)
{
    var l = new Label() 
            { 
                Text = message[i].ToString(), 
                AutoSize = true, 
                TextAlign = ContentAlignment.MiddleCenter 
            };
    int closure = i;
    mousemove
        .Delay(closure * 150)
        .Subscribe(e => 
            {
                l.Left = e.EventArgs.X + closure * 15 + 10;
                l.Top = e.EventArgs.Y;
                //Debug.WriteLine(l.Text);
            });
    Controls.Add(l);
}

当我移动鼠标时,字母似乎以随机顺序移动,如果我取消注释 Debug 行,我会看到同一个字母的多个事件......

有任何想法吗?我试过Throttle,但它似乎没有任何区别。我是否只是要求过多的 WinForms 来移动所有这些标签?

(交叉张贴在Rx 论坛上)

4

1 回答 1

2

从Rx 论坛发回的答案交叉(如果作者在这里并且想要声明它,我很好):

问题 #1:您使用的是旧位。Observable.Context 大约在 4 个版本前消失了。问题#2:Javascript 没有线程的概念,Rx 喜欢为你把东西放在其他线程上。

因此,使用最新的位,解决方案看起来像这样:

void Form1_Load(object sender, EventArgs e)
{
   Reactive("Time flies like an arrow");
}

private void Reactive(string msg)
{
    var mousemove = Observable.FromEvent<MouseEventArgs>(this, "MouseMove");
    var message = msg.ToCharArray();

    for(int i = 0; i < message.Length; i++)
    {
        var l = new Label()
        { 
            Text = message[i].ToString(), 
            AutoSize = true, 
            TextAlign = ContentAlignment.MiddleCenter 
        };
        int closure = i;
        mousemove
            .Delay(TimeSpan.FromSeconds(0.07 * i), Scheduler.Dispatcher)
            .Subscribe(e =>
            {
                l.Left = e.EventArgs.X + closure * 12 - 5;
                l.Top = e.EventArgs.Y + 15;
            });
        Controls.Add(l);
    }
}

注意 ObserveOnDispatcher 和 SubscribeOnDispatcher。这使我们接近了 Javascript 版本,但线程再次是这里的真正问题。

更新,在上面的代码中添加了来自 Jeff Van Gogh 的更正


只是为了好玩,这里是没有 Rx 的相同事物的模糊渲染:

private void Unreactive(string msg)
{
    var message = msg.ToCharArray();

    for(int i = 0; i < message.Length; i++)
    {
        var l = new Label()
        { 
            Text = message[i].ToString(), 
            AutoSize = true, 
            TextAlign = ContentAlignment.MiddleCenter 
        };
        Controls.Add(l);
        int closure = i;
        this.MouseMove += (s, e) => LabelDelayMove(closure, e, l);
    }
}

private void LabelDelayMove(int i, MouseEventArgs e, Label l)
{
    Point p = new Point(e.X + i * 12 - 5, e.Y - 15);
    var timer = new System.Threading.Timer((_) => LabelMove(l, p), null, i * 70, System.Threading.Timeout.Infinite);
}

private void LabelMove(Label l, Point location)
{
    this.BeginInvoke(new Action(() => l.Location = location));
}
于 2010-03-18T12:51:35.820 回答