Winforms эквивалент javascript setTimeout - PullRequest
8 голосов
/ 02 декабря 2010

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

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

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

Ответы [ 7 ]

29 голосов
/ 16 октября 2014

Я знаю, что это старый вопрос, но альтернативным решением было бы использовать 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

12 голосов
/ 02 декабря 2010

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

10 голосов
/ 09 октября 2012
    public void setTimeout(Action TheAction, int Timeout)
    {
        Thread t = new Thread(
            () =>
            {
                Thread.Sleep(Timeout);
                TheAction.Invoke();
            }
        );
        t.Start();
    }
2 голосов
/ 27 декабря 2018

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

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();
0 голосов
/ 13 июня 2017

Это мой способ, используйте функцию синтаксиса 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();
    }
}
0 голосов
/ 14 октября 2016

Я бы рекомендовал использовать реактивное программирование для этого. См. 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 мс) отличается от последнего выданного значения. 1010 *

0 голосов
/ 14 октября 2016
    public void setTimeout(Action act, int timeout)
    {
        Action action = () =>
        {
            Thread.Sleep(Timeout);
            act();
        };

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