Есть ли способ отложить обработчик событий (скажем, на 1 секунду) в Windows Forms

Если имена всех заполнителей названы, специальный словарь может использоваться для перехвата того, какие ключи пытались получить доступ и регистрироваться в массиве.

def format_keys(str_):
    class HelperDict(dict):
        def __init__(self):
            self._keys = []
        def __getitem__(self, key):
            self._keys.append(key)    
    d = HelperDict()
    str_.format_map(d)
    return d._keys

Обратите внимание, что если есть неназванные заполнители, IndexError будет увеличена на .format() (индекс кортежа за пределами диапазона).

13
задан Joel Coehoorn 16 March 2009 в 09:49
поделиться

7 ответов

Прежде, чем прийти к Вашему вопросу, просто считав сводный бит из основной страницы вопросов, таймер был точно, что я собирался предложить.

Это выглядит довольно чистым мне. Это означает, что можно легко "отменить" отложенное событие, если Вы должны, путем отключения таймера снова, например. Это также делает все в потоке UI (но без повторной входимости), который делает жизнь немного более простой, чем другие альтернативы могли бы быть.

5
ответ дан strager 16 March 2009 в 09:49
поделиться

Возможно, Вы могли сделать метод, который создает таймер?

void onButtonClick(object sender, EventArgs e)
{
    Delay(1000, (o,a) => MessageBox.Show("Test"));
}

static void Delay(int ms, EventHandler action)
{
    var tmp = new Timer {Interval = ms};
    tmp.Tick += new EventHandler((o, e) => tmp.Enabled = false);
    tmp.Tick += action;
    tmp.Enabled = true;
}
15
ответ дан Bengt 16 March 2009 в 09:49
поделиться

Если Вы только сделаете это для одного управления, то подход таймера будет хорошо работать. Более устойчивый подход, поддерживающий несколько средств управления и типов событий, выглядит примерно так:

class Event
{
   public DateTime StartTime { get; set; }
   public Action Method { get; set; }

   public Event(Action method)
   {
      Method = method;
      StartTime = DateTime.Now + TimeSpan.FromSeconds(1);
   }
}

Поддерживают Queue<Event> в Вашей форме и имеют события UI, которые должны быть отложены, добавляют их к очереди, например:

void onButtonClick( ..)
{
   EventQueue.Enqueue(new Event(MethodToCall));
}

Заставляют Ваш таймер отсчитать 10 раз приблизительно в секунду, и иметь его обработчик событий Галочки похожи на это:

void onTimerTick()
{
   if (EventQueue.Any() && EventQueue.First().StartTime >= DateTime.Now)
   {
      Event e = EventQueue.Dequeue();
      e.Method;
   }
}
5
ответ дан Robert Rossney 16 March 2009 в 09:49
поделиться

Можно использовать:

Thread.Sleep(1000);

, Который приостановит текущий поток в течение одной секунды. Таким образом, я сделал бы это...

С наилучшими пожеланиями!

-3
ответ дан MRFerocius 16 March 2009 в 09:49
поделиться

При поиске более необычного решения можно хотеть смотреть на мое Реактивное проект LINQ. Ссылка не показывает, как решить конкретную проблему, которую Вы имеете, но должно быть возможно решить во вполне изящном стиле с помощью техники, описанной там (в целом ряду с 4 статьями).

0
ответ дан Tomas Petricek 16 March 2009 в 09:49
поделиться

В моем решении используется System.Threading.Timer:

public static class ExecuteWithDelay
{
    class TimerState
    {
        public Timer Timer;
    }

    public static Timer Do(Action action, int dueTime)
    {
        var state = new TimerState();
        state.Timer = new Timer(o =>
        {
            action();
            lock (o) // The locking should prevent the timer callback from trying to free the timer prior to the Timer field having been set.
            {
                ((TimerState)o).Timer.Dispose();
            }
        }, state, dueTime, -1);
        return state.Timer;
    }
}
4
ответ дан 1 December 2019 в 20:30
поделиться

Для тех, кто ограничен .NET 2.0, вот еще один вариант полезного решения Bengt:

/// <summary>
/// Executes the specified method in a delayed context by utilizing
/// a temporary timer.
/// </summary>
/// <param name="millisecondsToDelay">The milliseconds to delay.</param>
/// <param name="methodToExecute">The method to execute.</param>
public static void DelayedExecute(int millisecondsToDelay, MethodInvoker methodToExecute)
{
    Timer timer = new Timer();
    timer.Interval = millisecondsToDelay;
    timer.Tick += delegate
                      {
                          // This will be executed on a single (UI) thread, so lock is not necessary
                          // but multiple ticks may have been queued, so check for enabled.
                          if (timer.Enabled)
                          {
                              timer.Stop();

                              methodToExecute.Invoke();

                              timer.Dispose();
                          }
                      };

    timer.Start();
}
3
ответ дан 1 December 2019 в 20:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: