Winforms相当于javascript setTimeout

时间:2010-12-02 02:31:12

标签: javascript .net winforms settimeout

是否有一个简单的解决方案/想法/策略来在WinForms应用程序中创建setTimeout等效函数。我主要是一个Web开发人员,但我不确定如何在WinForms应用程序中进行此操作。基本上,我有一个文本框,每次击键后我想运行一个任务来填充一个列表(比如一个自动完成类型的东西),但是如果用户继续输入字符,希望能够取消(例如clearTimeout)...

我唯一的猜测是可能使用BackGroundWorker并使其初始睡眠,当它处于休眠状态时,它可以被取消,如果用户停止输入密钥并且睡眠期结束,则它会继续运行任务等< / p>

(我不在乎一个例子是C#还是Vb.Net)

9 个答案:

答案 0 :(得分:28)

我知道这是一个老问题,但另一种解决方案是使用Task.Delay(delay).ContinueWith((task) => { /* Code */ });

Thread.Sleep vs Task.Delay?

或有await Task.Delay(delay);

https://social.msdn.microsoft.com/Forums/vstudio/en-US/345f0402-3af0-4f96-a501-073674883ba3/building-an-async-settimeout-function?forum=csharpgeneral

答案 1 :(得分:12)

您可以使用System.Timers.Timer:将AutoReset设置为false并使用Start / Stop方法并为Elapsed事件创建处理程序。

答案 2 :(得分:11)

    public void setTimeout(Action TheAction, int Timeout)
    {
        Thread t = new Thread(
            () =>
            {
                Thread.Sleep(Timeout);
                TheAction.Invoke();
            }
        );
        t.Start();
    }

答案 3 :(得分:3)

计时器实现:

public void SetTimeout(Action action, int timeout)
{
    var timer = new System.Windows.Forms.Timer();
    timer.Interval = timeout;
    timer.Tick += delegate (object sender, EventArgs args)
    {
        action();
        timer.Stop();
    };
    timer.Start();
}

答案 4 :(得分:2)

我可以提出以下建议

internal class Timeout : System.Timers.Timer
{
    public Timeout (Action action, double delay)
    {
        this.AutoReset = false;
        this.Interval = delay;
        this.Elapsed += (sender, args) => action();
        this.Start();
    }
}
// Example
var timeout = new Timeout(() => {
    Console.WriteLine("init 1");
}, 500);
timeout.Stop();

答案 5 :(得分:0)

    public void setTimeout(Action act, int timeout)
    {
        Action action = () =>
        {
            Thread.Sleep(Timeout);
            act();
        };

        new Thread(() => Invoke(action)).Start();
    }

答案 6 :(得分:0)

我建议使用反应式编程。有关Reactive Extensions for .NET的信息,请参阅https://github.com/Reactive-Extensions/Rx.NET;有关Reactive编程的一般信息,请参阅http://reactivex.io/

我担心我只熟悉JavaScript反应库,所以我不能给你一个C-Sharp的例子,但在JavaScript中它的工作方式是这样的:

Rx.Observable.fromEvent(..eventdetails..)
    .debounceTime(300)
    .distinctUntilChanged()
    .subscribe(eventHandler);

使用这样的设置,您可以链接运营商以映射和合并从源到订户的各种事件。上面的简单示例对一个事件(例如一个keyUp)做出反应,并等待300毫秒没有新的keyUp,然后调用eventHandler,但前提是新值(在300ms之后)与最后一个发射值不同。 / p>

答案 7 :(得分:0)

这是我的方式,使用C#7.0语法功能。 有些与js不同,当执行超时操作时,将无法清除。

internal static class JsStyleTimeout
{
    private static readonly ConcurrentDictionary<int, Thread> InnerDic;

    private static int _handle;

    static JsStyleTimeout()
    {
        InnerDic = new ConcurrentDictionary<int, Thread>();
    }

    public static int Set(Action action, int delayMs)
    {
        var handle = Interlocked.Increment(ref _handle);

        var thread = new Thread(new ThreadStart(delegate
        {
            Thread.Sleep(delayMs);
            InnerDic.TryRemove(handle, out var _);
            Task.Factory.StartNew(action);
        }));
        InnerDic.TryAdd(handle, thread);

        thread.Start();
        return handle;
    }

    public static void Clear(int handle)
    {
        if (InnerDic.TryRemove(handle, out var thread))
            thread.Abort();
    }
}

答案 8 :(得分:0)

您还可以使用:

Delay.Do(3000 /*in ms*/, () => { /* Do somthing */ });

Delay.Do在哪里:

using System;
using System.Timers;

public class Delay
{
    public static void Do(int after, Action action)
    {
        if (after <= 0 || action == null) return;

        var timer = new Timer { Interval = after, Enabled = false };

        timer.Elapsed += (sender, e) =>
        {
            timer.Stop();
            action.Invoke();
            timer.Dispose();
            GC.SuppressFinalize(timer);
        };

        timer.Start();
    }
}

注意:在UI线程中更新控件时,请使用Control.Invoke

Delay.Do(2000, () => { lblOk.Invoke((MethodInvoker)(() => { lblOk.Visible = false; })); });