2

I'm new and I am trying to figure something out. I have a simple program which executes a method either when an event happens or when my timer ticks. Lets just say the method takes 5 seconds to complete. During that 5 seconds an event could happen. What would I use/do to make sure my method isn't called while its already running.

Or is this something I would not have to worry about in a simple program, as it wouldn't run until the method is done anyway ?

A little background and example. I am using System.Windows.Forms.Timer, I am not using any threads or anything, and I just have a simple windows form application with a timer, a method to do stuff, and two event handlers.

Program{
  public Program(){
    DoSomething();
    Event.EventHappened += HandleEvent;
  }
  void DoSomething(){
    MyTimerVariable.Stop();
    InitMyTimer();
    //Just do something check network, access db write line, something
    //that in this example takes 5 secs for example purposes
    MyTimerVariable.Start();
  }
  void HandleEvent(){
    DoSomething();
  }
  void InitMyTimer(){
    // Create Timer, and add Timer tick event
  }
  void TimerTickedEvent(){
    DoSomething();
  }
}

I left a few things out of that program, but just was trying to show how simple it is. I was just thinking about making it more efficient so that say in the middle of doing "DoSomething()" an event is triggered, I wouldn't want two "DoSomething()"s method running.

3 Answers 3

5

As this is using a System.Windows.Forms.Timer instead of System.Threading.Timer, the event will be executed on the UI thread and therefore will not be executed out of sequence.

If you were using threading though, simply creating a private object lockObject = new object(); and locking it in the DoSomething() method, you will similarly ensure that the body of DoSomething does not get executed until it has finished.

3
  • So does that mean that in the middle of "DoSomething()" being run if an event happens it will just handle the event / call "DoSomething()" again immediately AFTER it has finished ?
    – RWhiten
    Feb 3, 2014 at 4:12
  • From the MSDN reference: The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released. msdn.microsoft.com/en-us/library/c5kehkcz.aspx
    – Stephen
    Feb 3, 2014 at 4:19
  • @RWhite Exactly.
    – Euphoric
    Feb 3, 2014 at 6:45
3

If the real intent is to make sure that you won't have multiple worker methods working at the same time the simplest way would be something like this:

bool isBusy = false;
void MyWorkerMethod()
{
  if(isBusy == true)
  {
    return;
  }

  try
  {
    isBusy = true;
    // do stuff
  }
  finally
  {
    isBusy = false;
  }
}

This way every time the timer ticks, it still executes your method but your method will immediately exit if it's in the middle of working with a minimum of fuss. If you use locking you'll get thread contention as things stack up waiting for the lock to free which I'm assuming is not what you want.

If you're super paranoid you could also look into the Interlocked.* APIs to make sure beyond a shadow of a doubt that you never have your worker running more than once but that may be overkill here.

3

I have to agree with @theficus for the code style.

However, not with implementation in detail.

I have had many cases in which more than one thread entered a code block only using his kind of boolean-check-implementation. Raising all kinds of havoc and confusion, since the assumed impossible actually happened. Any kind of thread locking algorithm which only works most of the time but not every time is IMHO pointless.

The Interlocked.* API for this use case is just as simple as the boolean-check-implementation and makes absolutely sure that only one thread enters the code block and all others continue.

private int isBusy = 0;

private void MyWorkerMethod()
{
  if(System.Threading.Interlocked.CompareExchange(ref this.isBusy, 1, 0) == 1)
  {
    return;
  }

  try
  {
    // do stuff
  }
  finally
  {
    this.isBusy = 0;
  }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.