Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#
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
 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 20-Nov-12 7:39am
dbzx734454
Comments
Earloc at 20-Nov-12 13:49pm
   
what should the timer do? just keep track of the elapsed time?
Sergey Alexandrovich Kryukov at 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
Member 9546601 at 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 at 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
Member 9546601 at 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..
Sergey Alexandrovich Kryukov at 20-Nov-12 14:41pm
   
Great. Then please accept my answer formally (green button) -- thanks.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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
  Permalink  
Comments
Marcus Kramer at 20-Nov-12 14:12pm
   
+5. I like it.
Sergey Alexandrovich Kryukov at 20-Nov-12 14:13pm
   
Thank you, Marcus.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

i think :
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
      
  }
  Permalink  
v2

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

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 355
1 _Amy 235
2 Peter Leow 185
3 Andreas Gieriet 180
4 Dave Kreskowiak 155
0 OriginalGriff 7,540
1 Sergey Alexandrovich Kryukov 6,462
2 Maciej Los 3,849
3 Peter Leow 3,653
4 CHill60 2,712


Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 20 Nov 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100