3

I have a Windows Application. We have implemented AutoSave functionality as background process.

Sample code is as below:

While(1)
{
    Thread.Sleep(60000) // 1 minute sleep
    DoAutoSaveAllControls();
}

I think this is bad functionality. Correct me if I am wrong. But, I want to improve performance and do this task after certain time interval, without doing Sleep. Also, is it good to do this in background process?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
iTSrAVIE
  • 846
  • 3
  • 12
  • 26
  • Also see this related question: [Compare using Thread.Sleep and Timer for delayed execution](http://stackoverflow.com/questions/391621/compare-using-thread-sleep-and-timer-for-delayed-execution) – Cody Gray - on strike Feb 02 '11 at 11:18

6 Answers6

4

A much better approach would be to use a timer. You can find out about the various different timers in the .NET framework from this excellent article:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

You are using WinForms, so a System.Windows.Forms.Timer will be just fine for you.

For example:

System.Windows.Forms.Timer tmrWindowsFormsTimer = new  System.Windows.Forms.Timer();
tmrWindowsFormsTimer.Interval = TimeSpan.FromMinutes(1);
tmrWindowsFormsTimer.Tick += new EventHandler(tmrWindowsFormsTimer_Tick);
tmrWindowsFormsTimer.Start();


private void tmrWindowsFormsTimer_Tick(object sender, System.EventArgs e) {
  tmrWindowsFormsTimer.Stop();
  DoAutoSaveAllControls();
}

This stops the timer after the first tick, effectively a fire-once timer.

ColinE
  • 68,894
  • 15
  • 164
  • 232
2

You can use Reactive Extenssions for this as well.It looks more natural and you can combine observables.

   var observable = Observable.Timer(
                  TimeSpan.FromMinutes(1), 
                  TimeSpan.FromMinutes(1)).Timestamp();

    using (observable.Subscribe()))
    {
         DoAutoSave();
    }
Andrey Taptunov
  • 9,367
  • 5
  • 31
  • 44
0

Thread.Sleep does not affect performance at all. In order to me is perfectly ok, but since your application is probably modifying the document in the UI thread you probably need to sincronize the save in order to avoid concurrent modifications. Just for this reason maybe it would be better to use a Timer instead of BackGroundWorker.

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
  • The `while + sleep` solution does hurt performance a little by occupying a Thread all the time. OK in a client, unacceptable in a server app. – H H Feb 02 '11 at 11:17
  • `Thread.Sleep` is a bad solution for plenty of reasons. [Interesting related reading](http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx). – Cody Gray - on strike Feb 02 '11 at 11:20
  • a Sleeping thread does not consume CPU. Is not an idea to encourage, but sayng that is a performance leak is wrong too – Felice Pollano Feb 02 '11 at 11:21
  • 2
    That's still wrong. Spinning a thread in the background consumes resources because you're running an additional thread. Threads aren't free, even if you're not doing anything on them. I agree, the performance impacts aren't severe, but there are much better ideas. – Cody Gray - on strike Feb 02 '11 at 11:23
0

You're right, it's not really a good use of a thread. Take a look at the Timer class.

Rich Tebb
  • 6,806
  • 2
  • 23
  • 25
0

I think you need to trigger save functionality from the calling code (that knows if any changes had already happaned). So that saving thread could know for sure that calling thread has made some changes to save.

This is not an answer for this question, just maybe recommendation. So if you are calling Save from inside of timer, you should verify first if any change happened. To do that you'll need some additional variable, that would be common for working thread and saving thread. If working thread did change something, it triggers that var to true. When saving, if var is true - then saving is needed. After saving - change common var to false.

Sasha Reminnyi
  • 3,442
  • 2
  • 23
  • 27
0

You can use System.Timers.Timer to start a process after certain interval, check the sample snippet

    aTimer = new System.Timers.Timer(10000);

    // Hook up the Elapsed event for the timer.
    aTimer.Elapsed += new ElapsedEventHandler(YourHandlerMethod);

    // Set the Interval to 2 seconds (2000 milliseconds).
    aTimer.Interval = 2000;
    aTimer.Enabled = true;
RameshVel
  • 64,778
  • 30
  • 169
  • 213