1

具体来说,如果按键的持续时间大于阈值(T),我正在尝试模拟执行操作。

我正在尝试使用没有状态变量的 Reactive Extensions .NET(稳定的 1.0 版本)来做到这一点。

这是我的输入和我需要的大理石图:

让 T = 3 (所以 4 dddd 没有按键事件构成“按键按下”)

keyDown: --dddd---dd--d-dddddddddd----

keyUp: ------------u-----u--u----------------u--

所需:--------a-------------a---------

这是我想出的一些示例代码,但它使用了状态变量。

var keyDownStream = Observable.FromEventPattern<KeyEventArgs>(this, "KeyDown").Where(args => args.EventArgs.Key == Key.OemPeriod);
        var keyUpStream = Observable.FromEventPattern<KeyEventArgs>(this, "KeyUp").Where(args => args.EventArgs.Key == Key.OemPeriod);

        var repeatGuard = false;
        keyUpStream.Subscribe(x => repeatGuard = false);
        keyDownStream
            .DelayOrCancel(TimeSpan.FromSeconds(2.0), keyUpStream)
            .Where(_ => repeatGuard == false)
            .Do(_ =>
            {
                repeatGuard = true;
            })
            .Subscribe(
                result =>
                {
                    Console.WriteLine("KeyHold");
                }
            );

public static class JustinsRx
{
    public static IObservable<T> DelayOrCancel<T, TCancel>(this IObservable<T> source,
                                     TimeSpan delay,
                                     IObservable<TCancel> cancel)
    {
        //argument checking skipped
        return from s in source
               from i in Observable.Timer(delay).TakeUntil(cancel)
               select s;
    }
}
4

2 回答 2

2

这行得通,但我觉得它可以做得更短。

var firstKeyDowns = Observable
    .Merge(keyDownStream.Select(_ => 'd'), keyUpStream.Select(_ => 'u'))
    .DistinctUntilChanged()
    .Where(c => c == 'd');
var query = from s in firstKeyDowns 
            from i in Observable.Timer(delay).TakeUntil(keyUpStream)
            select s;

编辑:这是我认为更好的不同版本:

var noRepeats = Observable
    .Merge(keyDownStream.Select(_ => 'd'), keyUpStream.Select(_ => 'u'))
    .DistinctUntilChanged();
var query = noRepeats
    .Throttle(delay)
    .Where(c => c == 'd');
于 2012-04-05T03:56:17.580 回答
1

这对我有用:

var timer = Observable.Timer(TimeSpan.FromSeconds(1.0));

var query =
    keyDownStream
        .Select(_ =>
            keyUpStream
                .Select(_ => 'u')
                .Amb(timer.Select(_ => 't'))
                .Take(1)
                .Where(x => x == 'u')
                .Select(_ => Unit.Default))
        .Switch();
于 2012-04-05T03:09:49.777 回答