使用接收与取消执行延迟作用一次,每个窗口 [英] Using Rx to execute delayed action once with cancellation for each window

查看:182
本文介绍了使用接收与取消执行延迟作用一次,每个窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

具体我试图模拟执行一个动作,如果键被按下的持续时间大于阈值(T)。

我试图做到这一点使用无功扩展.NET(稳定的1.0版本)的无状态变量。

下面是我输入的大理石图,我所需要的:

让T = 3(SO 4 DDDD没有钥匙了事件一补键按住)

的keyDown:--dddd --- DD - D-DDDDDDDDDD ----

KEYUP:-----------ü-----ü - U ---------------ü -

期望:--------一---------------一----------

下面是一些例子code我想出了工作,但使用的状态变量。

  VAR keyDownStream = Observable.FromEventPattern< KeyEventArgs>(这一点,的KeyDown),其中(参数=> args.EventArgs.Key == Key.OemPeriod)。
        VAR keyUpStream = Observable.FromEventPattern< KeyEventArgs>(这一点,的KeyUp),其中(参数=> args.EventArgs.Key == Key.OemPeriod)。

        VAR repeatGuard = FALSE;
        keyUpStream.Subscribe(X => repeatGuard = FALSE);
        keyDownStream
            .DelayOrCancel(TimeSpan.FromSeconds(2.0),keyUpStream)
            。凡(_ => repeatGuard ==假)
            。做(_ =>
            {
                repeatGuard = TRUE;
            })
            。订阅(
                结果=>
                {
                    Console.WriteLine(KeyHold);
                }
            );

公共静态类JustinsRx
{
    公共静态的IObservable< T> DelayOrCancel< T,TCancel>(此的IObservable< T>源,
                                     时间跨度延迟,
                                     的IObservable< TCancel>取消)
    {
        //参数检查跳过
        从s源返回
               从我在Observable.Timer(延迟).TakeUntil(取消)
               选择S;
    }
}
 

解决方案

这工作,但我觉得它可能会更短。

  VAR firstKeyDowns =观测
    .Merge(keyDownStream.Select(_ =>D),keyUpStream.Select(_ =>'U'))
    .DistinctUntilChanged()
    。凡(C =以及c =='D');
在firstKeyDowns VAR的查询=从s
            从我在Observable.Timer(延迟).TakeUntil(keyUpStream)
            选择S;
 

编辑:这是一个不同的版本,我认为这是一个更好一点:

  VAR noRepeats =观测
    .Merge(keyDownStream.Select(_ =>D),keyUpStream.Select(_ =>'U'))
    .DistinctUntilChanged();
VAR的查询= noRepeats
    .Throttle(延迟)
    。凡(C =以及c =='D');
 

specifically I am trying to simulate performing an action if the key is held down for a duration greater than Threshold (T).

I am trying to do this using Reactive Extensions .NET (The stable 1.0 version) without state variables.

Here's the marble diagram of my inputs and what I need:

let T = 3 (so 4 dddd without a key up event make up a "key held down")

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

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

desired: --------a---------------a----------

Here's some example code I came up with that works but uses a state variable.

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;
    }
}

解决方案

This works, but I feel that it could be made shorter.

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;

EDIT: Here's a different version that I think is a bit nicer:

var noRepeats = Observable
    .Merge(keyDownStream.Select(_ => 'd'), keyUpStream.Select(_ => 'u'))
    .DistinctUntilChanged();
var query = noRepeats
    .Throttle(delay)
    .Where(c => c == 'd');

这篇关于使用接收与取消执行延迟作用一次,每个窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆