处理C#中的竞争条件

时间:2010-07-21 21:20:33

标签: c# race-condition

我正在编写一个带有分层通信接口的应用程序 这样做是为了从应用程序的用户界面部分抽象出通信,并使其更具可扩展性/可维护性 例如:

alt text

将上图中的每个方框视为一个单独的类 通用通信接口填充描述事务数据和通信“运行状况”的字符串变量,这些变量又通过一系列公共函数调用复制到应用程序。例如,应用程序将调用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由类中的其他函数异步填充 我相信在string sRetVal = this.sText;和下一行this.sText = null;之间会发生竞争状况 有人可以建议一种方法来避免或阻止这种竞争条件吗?是否会使用StringBuilder帮助,还是有其他方式我应该这样做?

3 个答案:

答案 0 :(得分:4)

您可能应该在想要触摸this.sText的任何时候获取锁定 - 在更新它的功能以及GetText功能中。这将确保一次只有一个线程正在弄乱它,因为(假设您的线程有锁)其他线程将坐下并等待当前线程完成。

我建议您使用StringBuilder,部分是为了简化锁定,因为锁定碰巧被执行的字符串,或者在锁定操作的中间切换(因此从局外人的角度解锁)可能导致真正糟糕的魔力。 这样的事情会有所帮助:

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

或者,您可以锁定this,但这很难看 - 您的锁应该在内部,尽可能私密,以避免奇怪的副作用(如果某些其他对象试图获取锁定在这个对象上 - 当sbText被改变时,它不能这样做。

答案 1 :(得分:1)

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;
   }
}    
在你的

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

答案 2 :(得分:1)

这个代码肯定不会在线程环境中工作,因为你不保护sText。你需要锁定访问它的每个人。