Threading question

  • Thread starter Thread starter James
  • Start date Start date
J

James

Hi,

I have a windows form and a class. A method of the class
returns a data view object which the form binds to a
control. The data can be refreshed by clicking a refresh
button or waiting for a timer on the form to expire. Both
methods call the same function on the class. I have
recently developed a problem where it appears that when
both events occur and try to access the funtion on the
class at the same time the app blows up. How can I ensure
that the function is only called by one place at a time?
I tried using a mutex (created it in the class, called
the waitone function at the beginging of the function and
release just before the return) but the app not only
crashes with this approach, it hangs after the crash.

I would appreciate any help. Thanks!
 
There might be a better way, but you could declare a bool in your class and
set it to false in your constructor. Then when your function is called have
it first check the static bool. If it's true, then do nothing, if it's
false, set it to true and then run the rest of your function. At the end of
you function, set it back to true. Something like this:

private bool IsRunning

public MyClass()
{
IsRunning = false;
....
}

public void myFunction()
{
if (!IsRunning)
{
IsRunning = true;
// Do you stuff here
....
IsRunning = false;
}
}

I guess in theory it could still run at exactly the same time, but it would
be extremely unlikely that the function would be started a second time in
the time it takes to check one bool and then set it to true.
 
Hi,
I guess in theory it could still run at exactly the same time, but it would
be extremely unlikely that the function would be started a second time in
the time it takes to check one bool and then set it to true.
Believe me this will happen. Chances are not small.

My suggestion:
Your idea with the mutex is ok (I suggest using Monitor instead). The
problem is different, though
As far as I understand the shared function updates the UI. That means it
should be executed on the thread that owns the windows handle. Even if the
there is only one call and this call is made from a thread different than
the UI one it might cause the application to *hang*.
You haven't mentioned anything about using worker threads. If you don't have
worker threads you don't have to have problems with synchronization. Anyway
you might have different threads even if you don't use them explicitly.
What kind of timer do you use. If you use windows form's timer it seems like
you don't have to have problems as long as the Tick event handler will be
executed in the UI thread.
If you use System.Timers' timer or System.Threading's timer you may have
problems as long they executes their event handlers in a thread from the
thread pool.


Try to do something like this

void ButtonClickHandler(object sender, EventArgs e)
{
//button handler runs on the UI thread so you don't need to do anything
special.
//Check the monitor. If it is already locked just return. You don't need
to update anything this time as long as it has been taken care of
if(!Monitor.TryEnter(this)) return;
DoUpdate();
Monitor.Exit(this);
}

void TimerEventHandler(object sender, XXXEventArgs e)
{

//I presume that this event is handled in the control which has to be
updated so *this* is reference to the control.
if(this.InvokeRequired)
{
//Check the monitor. If it is already locked just return. You don't
need to update anything this time as long as it has been taken care of
if(!Monitor.TryEnter(this)) return;
//You should decide which overload of Invoke method to use
//You can save the TimerEventHandlerDelegate delegate object in
order not to create it every time the timer fires the event.
this.Invoke(new TimerEventHandlerDelegate(TimerEventHandler), ....);
Monitor.Exit(this)
}
DoUpdate();
}

void DoUpdate()
{
//update
}

You may consider to use designated object for locking with the Monitor.
Locking *this* is not always a good idea as long as you might have several
independent critical sections.
 
Back
Top