Jim Fell
Jim Fell

Reputation: 14254

Handling Race Conditions in C#

I'm writing an application with a layered communications interface.
This was done to abstract the communications from the user-interface part of the application and also to make it more scaleable/maintainable.
For instance:

alt text

Consider each box in the figure above as a separate class.
The Generic Comms Interface populates string variables describing the transacted data and comms "health," which are in turn copied up to the Application through a series of public function calls. For example, the Application would make a call to the App-Sub-System:

class Application
{
   private void SomeUpdateFunction()
   {
      this.textBox1.AppendText(this.AppSubSystem.GetText());
   }
}

class AppSubSystem
{
   public string GetText()
   {
      return this.GenericCommsInterface.GetText();
   }
}

class GenericCommsInterface
{
   public string GetText()
   {
      string sRetVal = this.sText; // sText is populated by other functions in the class.
      this.sText = null; // Suspected race condition is here.
      return sRetVal;
   }
}

sText is populated asynchronously by other functions in the class.
I belive a race condition is happening between string sRetVal = this.sText; and the following line this.sText = null;.
Can someone suggest a way to avoid or prevent this race condition? Would using StringBuilder help, or is there another way that I should be doing this?

Upvotes: 8

Views: 6437

Answers (3)

µBio
µBio

Reputation: 10758

public string GetText()
{
   lock( someObject )
   {
      string sRetVal = this.sText; // sText is populated by other functions in the class.
      this.sText = null; // Suspected race condition is here.
      return sRetVal;
   }
}    

in your set

lock( someObject )
{
    //...
    this.sText = value;
}

Upvotes: 0

cHao
cHao

Reputation: 86534

You should probably be acquiring a lock any time you want to touch this.sText -- in the functions that update it, as well as your GetText function. This would ensure that only one thread at a time is messing with it, as (assuming your thread has the lock) other threads will sit and wait til the current thread is done.

I'd recommend you use a StringBuilder, partly to simplify locking, as locking a string that happened to be interned, or one switched out in the middle of the locked operation (and thus unlocked, from an outsider's perspective) could cause real bad mojo. Something like this would help:

lock (this.sbText)
{
    sRetVal = this.sbText.ToString();
    this.sbText.Length = 0;
}

Alternatively, you could lock on this, but that's ugly -- your locks should be inside, as private as possible, in order to avoid weird side effects (like if some other object were trying to acquire a lock on this object -- it couldn't do so while sbText was being altered).

Upvotes: 5

Loren Pechtel
Loren Pechtel

Reputation: 9093

This code most certainly won't work in a threaded environment as you aren't protecting sText. You need to lock everybody that accesses it.

Upvotes: 1

Related Questions