Click here to Skip to main content
15,881,248 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I am trying to write this application. Currently I have a BackgroundWorker thread to do some operation. Inside the worker thread, I have this loop to do the work n amount of times and also a delay time in which I used to pause the loop.

Currently it looks something like this
C#
 bg_DoWork(object sender, DoWorkEventArgs e)
{ ......
  repeat = 10;
  int i = 0;
  int delay = 5;

  while ( i < repeat)
  {  //do some work 
      i++;
      //pause for n seconds
      System.Threading.Thread.Sleep(delay*1000)
  }


This works fine. However, I want have a timer to count down or up during the delay duration, in the UI thread. I tried creating a timer in the background thread but the tick event won't invoke because it is not in the UI thread. What is the best way of doing this?

Thank you,
dbzx
Posted
Comments
earloc 20-Nov-12 13:49pm    
what should the timer do? just keep track of the elapsed time?
Sergey Alexandrovich Kryukov 20-Nov-12 13:52pm    
Yes, the need of the timer is questionable. Chances are, it's not needed. However, I've chosen to advice on timer use. The problem is pretty usual -- please see my answer.
--SA
dbzx734 20-Nov-12 13:57pm    
well i just want to show the accurate delay of the loop on the UI thread during the pause.
Sergey Alexandrovich Kryukov 20-Nov-12 14:15pm    
The thing is: you can still use a loop with Sleep, but for exact timing just poll the current time using System.DateTime.Now or Stopwatch (for very high accuracy). These are not timers; but a timer might not be needed.
You just need to show accurate delay time -- here you go. Got the idea? This is much better than a timer, safer...
--SA
dbzx734 20-Nov-12 14:36pm    
Thank you for your response. It helped a lot. I think I figured out how to to it. Loop sleep at intervals of 1 second and update the textbox(which stores the time) using invoke and etc..

I'm still not sure that you really need that timer, as you did not really explain the purpose, but if you do, the best way is not using System.Windows.Forms.Timer. There are at least three more timers in .NET, and this one is the worst. You can use it only if you have no requirements to accuracy and can tolerate the 100% or more of timing error. The only one good but questionable feature of this timer is that its use is simplified: its tick event handler is also called in UI thread, which is, in your case, also a hassle. (However, you did not tag your UI library, so I'm not sure you tried to work with System.Windows.Forms, but I think this is pretty likely.)

You can choose from System.Threading.Timer, System.Timers.Timer or System.Windows.Threading.DispatcherTimer (WPF). Most likely, you would rather prefer System.Timers.Timer:
http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx[^].

The only difficulty is: this timer tick event handler is not guaranteed to be called in the UI thread, so you will need to use the same very invocation mechanism you would use in a non-UI thread to delegate some UI operation to be executed in the UI thread. You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
 
Share this answer
 
Comments
fjdiewornncalwe 20-Nov-12 14:12pm    
+5. I like it.
Sergey Alexandrovich Kryukov 20-Nov-12 14:13pm    
Thank you, Marcus.
--SA
i think :
C#
bg_DoWork(object sender, DoWorkEventArgs e)
{ ......
  repeat = 10;
  int i = 0;
  int delay = 5;
  DateTime d=DateTime.Now;
 
  while ( i < repeat)
  { 
      TimeSpan ts=d.Subtract(DateTime.Now); 
      if(ts.Seconds==5)
        {
         //do some work 
         i++;
         d=DateTime.Now;
        }
      else
      //count down/up any other variable
      
  }
 
Share this answer
 
v2

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900