如果方法A的调用时间不超过N秒,则调用方法B [英] Call Method B if method A is not called for more than N seconds

查看:71
本文介绍了如果方法A的调用时间不超过N秒,则调用方法B的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在N秒之后,我正在使用以下代码来调用方法B.如果方法A在N秒超时内再次被调用,我必须将计时重新设置为N秒.

I'm using following code to call Method B after N seconds method A is called. If method A is called again within the N seconds timeout, i have to reset the time counting back to N seconds.

我无法在项目中引用System.Windows.Form,因此无法使用System.Windows.Form.Timer.

I cannot reference System.Windows.Form in my project, so I cannot use System.Windows.Form.Timer.

方法B必须在调用线程A的同一线程中调用.

The method B must be called in the same thread A is called.

private void InitTimer()
{
    timer = new BackgroundWorker();
    timer.WorkerSupportsCancellation = true;
    timer.WorkerReportsProgress = true;
    timer.DoWork += delegate(object sender, DoWorkEventArgs e)
                    {
                        var st = DateTime.Now;
                        while (DateTime.Now.Subtract(st).TotalSeconds < 10)
                        {
                            if (timer.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }
                        }

                    };
    timer.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
                    {
                        if (!e.Cancelled)
                        {    
                            MethodB();
                        }
                        else
                        {
                            timer.RunWorkerAsync();
                        }
                    };
}



public void MethodA()
{
     if (timer.IsBusy)
         timer.CancelAsync();
     else
         timer.RunWorkerAsync();

}

public void MethodB()
{
     //do some stuff

}

实际上,代码可以工作,但是我认为这有点令人困惑.您知道是否有最佳实践来达到相同的结果?

Actually the code work, but i think it's a bit confounding. Do you know if there is a best practices to achieve the same result?

推荐答案

您陷入.NET 2.0实在可惜,因为

It's a shame you're stuck on .NET 2.0, because Rx extensions has a Throttle method that achieves this effect quite elegantly.

悲伤的Rx至少需要.NET 3.5 SP1.

Sadly Rx requires at least .NET 3.5 SP1.

哦,好吧!您始终可以使用 System.Threading.Timer 即可完成此操作.可以通过利用当前的 SynchronizationContext (这是 BackgroundWorker 所做的事情)来提供同步.

Oh well! You can always use a System.Threading.Timer to get this done instead. Synchronization can be provided by leveraging the current SynchronizationContext (this is what BackgroundWorker does).

这是 LaggedMethodPair 类的示意图,以说明此方法.该类在其构造函数中接受三个输入:一个将按需执行的 Action ,另一个将充当回调的 Action ,当给定的超时时间过去时,该回调将被调用,当然还有超时本身:

Here's a sketch of a LaggedMethodPair class to illustrate this approach. The class takes three inputs in its constructor: an Action to be performed on-demand, another Action to serve as the callback that will be invoked when a given timeout has elapsed, and, of course, the timeout itself:

public sealed class LaggedMethodPair
{
    private SynchronizationContext _context;
    private Timer _timer;

    private Action _primaryAction;
    private Action _laggedCallback;
    private int _millisecondsLag;

    public LaggedMethodPair(Action primaryAction,
                            Action laggedCallback,
                            int millisecondsLag)
    {
        if (millisecondsLag < 0)
        {
            throw new ArgumentOutOfRangeException("Lag cannot be negative.");
        }

        // Do nothing by default.
        _primaryAction = primaryAction ?? new Action(() => { });

        // Do nothing by default.
        _laggedCallback = laggedCallback ?? new Action(() => { });

        _millisecondsLag = millisecondsLag;

        _timer = new Timer(state => RunTimer());
    }

    public void Invoke()
    {
        // Technically there is a race condition here.
        // It could be addressed, but in practice it will
        // generally not matter as long as Invoke is always
        // being called from the same SynchronizationContext.
        if (SynchronizationContext.Current == null)
        {
            SynchronizationContext.SetSynchronizationContext(
                new SynchronizationContext()
            );
        }

        _context = SynchronizationContext.Current;

        ResetTimer();

        _primaryAction();
    }

    void ResetTimer()
    {
        _timer.Change(_millisecondsLag, Timeout.Infinite);
    }

    void RunTimer()
    {
        _context.Post(state => _laggedCallback(), null);
    }
}

我编写了一个示例Windows Forms应用程序来演示此类.该表单包含一个 LaggedMethodPair 成员,其超时时间为2000毫秒.它的 primaryAction 将一个项目添加到列表视图.其 laggedCallback 将高亮显示的项目添加到列表视图中.

I wrote a sample Windows Forms app to show this class in action. The form contains a LaggedMethodPair member with a timeout of 2000 ms. Its primaryAction adds an item to a list view. Its laggedCallback adds a highlighted item to the list view.

您可以看到代码按预期运行.

You can see that the code runs as expected.

这篇关于如果方法A的调用时间不超过N秒,则调用方法B的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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