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:
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?
Race condition can be handled by Mutex or Semaphores. They act as a lock allows a process to acquire a resource based on certain requirements to prevent race condition.
What are race conditions? Race conditions in software or any system occur when the desired output requires that certain events occur in a specific order but that the events don't always happen in that order. There is a 'race' between the events and if the wrong events win, the program fails.
A simple example of a race condition is a light switch. In some homes, there are multiple light switches connected to a common ceiling light. When these types of circuits are used, the switch position becomes irrelevant. If the light is on, moving either switch from its current position turns the light off.
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).
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With