Winforms эквивалент javascript setTimeout

Есть ли простое решение/идея/стратегия для создания эквивалентной функции setTimeout в приложении WinForms. Я в первую очередь веб-разработчик, но не уверен, как это сделать в приложении WinForms. В принципе, у меня есть текстовое поле, и после каждого нажатия клавиши я хочу запустить задачу, чтобы заполнить список (например, auto-complete type thingy), но хочу иметь возможность отменить (например, clearTimeout), если пользователь продолжает вводить символы...

Мое единственное предположение - возможно, использовать BackGroundWorker и сначала скомпоновать его, и пока он спит, его можно отменить, если пользователь перестает вводить ключи и заканчивается период ожидания, затем он запускает и запускает задачу и т.д.

(мне все равно, что пример С# или Vb.Net)

Ответ 1

Вы можете использовать System.Timers.Timer: установить AutoReset в значение false и использовать методы Start/Stop и создать обработчик для события Elapsed.

Ответ 3

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

Ответ 4

Я могу предложить следующее

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

Реализация таймера:

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

Ответ 6

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

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

Ответ 7

Я бы рекомендовал использовать для этого реактивное программирование. См. https://github.com/Reactive-Extensions/Rx.NET для реактивных расширений для .NET и http://reactivex.io/ для общей информации об активном программировании.

Я боюсь, что я знаком с реактивной библиотекой JavaScript, поэтому я не могу дать вам пример C-Sharp, но в JavaScript он будет работать примерно так:

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

Используя такую ​​настройку, вы можете привязать операторов к отображению и объединению всех видов событий от источника к подписчику. Простой пример выше относится к событию, например keyUp, и ожидает, пока не будет нового keyUp за 300 мс, а затем вызовет eventHandler, но только если новое значение (после 300 мс) отличается от последнего испущенного значения.

Ответ 8

Это мой путь, используйте синтаксис С# 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();
    }
}

Ответ 9

Вы также можете использовать:

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

Примечание: при обновлении элемента управления в потоке пользовательского интерфейса используйте Control.Invoke:

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