Click here to Skip to main content
15,880,967 members
Articles / General Programming
Tip/Trick

Execute later for delayed action

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
12 Aug 2011CPOL1 min read 15.1K   2  
Code blocks are executed asyncronously in the UI thread after a given timeout.
This is the trick to be used in order invoke some piece of code in main UI thread after some delay without going through the BeginInvoke() stuff everytime. A possible use case is where an operation regarding an external device is performed and its status must be checked after some time. If device does not operate as requested or it does not respond at all, UI thread can show warning messages to inform the operator. Since warning messages will be shown in the UI thread, it is important that the delayed code is executed in the UI thread as well.

Timers and BeginInvoke with delegates can be used here as well but they make the code harder to follow in the case of many events and delegates.

Following class wraps up the delayed processing operations. It has a static method
which can be called from any thread. BackgroundWorker's RunWorkerCompleted method is used to execute the code later in the UI thread. Since the callback is executed in the UI thread, all operations on the UI control can be performed.
C#
 public class DelayedAction
{ 
   public static void Do(int timeout, MethodInvoker callback)
   {
      BackgroundWorker worker = new BackgroundWorker();
      worker.DoWork += new DoWorkEventHandler(DoWork);
      worker.RunWorkerCompleted += new WorkerCompleted(RunWorkerCompleted);
      worker.RunWorkerAsync(new object[] { timeout, callback});
   }

   // Notified when our thread terminates
   static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
   {
      MethodInvoker callback = (MethodInvoker)e.Result;
      callback.Invoke();
   }

   // Do nothing but sleep
   static void DoWork(object sender, DoWorkEventArgs e)
   {
      object[] args = (object[])e.Argument;
      Thread.Sleep((int)args[0]);
      e.Result = args[1]; // return callback
   }
}


After that we can easily use that class in our main UI thread as follows where we can easily track the business logic.
C#
...
label1.Text = "Powering on device";
device.PowerOn();

//Check device status 10 seconds later

DelayedAction.Do(10000, (MethodInvoker)delegate()
{
   // UI can be direcly manipulated here
   // This code executes in the UI thread.
   if( device.IsPowered() == false )
   {
      label1.Text = "Device operation failed";
   }
   else
   {
      label1.Text = "Device OK.";
   }
 });
 ...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --