C#线程加入if块,其条件返回false

时间:2014-08-12 10:01:35

标签: c# multithreading locking conditional-statements

许多线程正在访问这段代码

    // All code is from same class

    public void ExecuteCommand(IAsciiCommand command, IAsciiCommandSynchronousResponder responder)
    {
        lock (commander)
        {
            if (commander.IsConnected)
            {
                commander.ExecuteCommand(command, responder);
            }
        }
    }

    public void Disconnect()
    {
        var tmp = commander.IsConnected;
        commander.Disconnect();
        if (commander.IsConnected != tmp && !commander.IsConnected)
        {
            OnPropertyChanged("IsConnected");
        }
    }

最终我得到了这个:Error

这怎么可能,该线程被访问到if语句,其条件返回false?我该如何解决?

3 个答案:

答案 0 :(得分:2)

这种情况正在发生,因为检查和调用缺少原子性。以下是可能导致异常的一系列事件:

  • 两个线程A和B同时达到该条件
  • 线程A检查条件,返回true,进入if
  • 同时,线程调度程序判定线程A已耗尽其时间段并暂停它
  • 主题B调用Disconnect
  • 线程调度程序恢复线程A,它位于if条件内。但是,该命令不再连接
  • 这会导致异常

您可以通过在commander内锁定Disconnect()来解决此问题。

public void Disconnect()
{
    bool doEvent;
    lock(commander) {
        var tmp = commander.IsConnected;
        commander.Disconnect();
        doEvent = (commander.IsConnected != tmp && !commander.IsConnected)
    }
    // Run OnPropertyChanged outside the locked context 
    if (doEvent)
    {
        OnPropertyChanged("IsConnected");
    }
}

答案 1 :(得分:1)

您需要锁定静态对象。现在,您根据正在使用的对象(commander)创建单独的锁。试试这个:

public class WhatEverClassHasTheExecuteCommandMethod
{
     private static object _lock = new object();

     public void ExecuteCommand(IAsciiCommand command, IAsciiCommandSynchronousResponder responder)
     {
          lock (_lock)
              if (commander.IsConnected)                  
                 commander.ExecuteCommand(command, responder);
     }
}

答案 2 :(得分:1)

如果您在断开连接时未锁定,则完全有可能获得竞争条件。基本解决方案是在Disconnect方法中添加一个锁:

public void Disconnect()
{
    lock (commander)
    {
        var tmp = commander.IsConnected;
        commander.Disconnect();
        if (commander.IsConnected != tmp && !commander.IsConnected)
            OnPropertyChanged("IsConnected");
    }
}
相关问题