Is there a way to delay an event handler (say for

2020-05-23 08:16发布

I need to be able to delay the event handlers for some controls (like a button) to be fired for example after 1 sec of the actual event (click event for example) .. is this possible by the .net framework ?

I use a timer and call my code from the timer's tick event as below but I am not sure if this is the best approach !

void onButtonClick( ..)
{
   timer1.Enabled = true;
}

void onTimerTick( ..)
{
   timer.Enabled = false; 

   CallMyCodeNow();
}

8条回答
甜甜的少女心
2楼-- · 2020-05-23 08:21

Perhaps you could make a method that creates the timer?

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;
}
查看更多
SAY GOODBYE
3楼-- · 2020-05-23 08:22

If you're only doing this for one control, the timer approach will work fine. A more robust approach supporting multiple controls and types of events looks something like this:

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

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

Maintain a Queue<Event> in your form and have UI events that need to be delayed add them to the queue, e.g.:

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

Make your timer tick 10 times a second or so, and have its Tick event handler look like this:

void onTimerTick()
{
   if (EventQueue.Any() && EventQueue.First().StartTime >= DateTime.Now)
   {
      Event e = EventQueue.Dequeue();
      e.Method;
   }
}
查看更多
Juvenile、少年°
4楼-- · 2020-05-23 08:24

Before coming to your question, just having read the summary bit from the main questions page, a timer was exactly what I was going to suggest.

This looks pretty clean to me. It means you can easily "cancel" the delayed event if you need to, by disabling the timer again, for example. It also does everything within the UI thread (but without reentrancy), which makes life a bit simpler than other alternatives might be.

查看更多
Deceive 欺骗
5楼-- · 2020-05-23 08:24

You can use:

Thread.Sleep(1000);

That will pause the current Thread for one second. So I would do that...

Best Regards!

查看更多
forever°为你锁心
6楼-- · 2020-05-23 08:29

For those limited to .NET 2.0, here is another take on Bengt's helpful solution:

/// <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();
}
查看更多
虎瘦雄心在
7楼-- · 2020-05-23 08:33

If you're looking for a more fancy solution, you may want to take a look at my Reactive LINQ project. The link doesn't show how to solve the particular problem you're having, but it should be possible to solve in quite an elegant style using the technique described there (in the whole 4-article series).

查看更多
登录 后发表回答