意外的静态变量行为

时间:2013-10-01 15:51:35

标签: c# .net static-members

这是我的代码示例

internal static class Communication
{
    ...

    private static byte _lastAnswer;

    ...

    static void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            lock (SerialDataLock)
            {
                ...
                 _lastAnswer = data[0];
                ...
            }
        }
    }
}

Serial_DataReceivedSerialPort.DataReceived事件的处理程序,数据是从串行端口获取的本地字节数组。问题在于_lastAnswer的意外行为。调试器显示有时它没有被分配,有时它被分配但是在块的末尾突然返回它的先前值。

例如,我尝试通过主线程

中的公共属性读取_lastAnswer
public static byte LastAnswer
    {
        get
        {
            Program.DataRecievedEvent.Reset(); 
            byte rtn = _lastAnswer;
            _lastAnswer = ErrorCode;
            Debug.Assert(rtn!=0xff);
            _lastAnswer = 0xff; //return member to default value
            return rtn;
        }
    }

Assert不会抛出任何异常,但Main if (answer == 0xff)中的下一个块返回true

经过一天的发现,我发现在其他非静态类中使字段_lastAnswer非静态并引用它可以解决问题。但这看起来很糟糕,并没有回答这个话题。

1 个答案:

答案 0 :(得分:0)

您正在访问变量而不锁定它。这可能有许多问题。

  1. 第二个代码段中没有引入内存障碍,因此允许CPU在多线程上下文中进行不合法的优化。 (它可以使用变量的缓存值,而不会像您认为的那样经常更新它们。)

  2. 在您第一次抓住变量并且在第二次抓取变量之前,没有任何东西阻止第一个代码段变异。

  3. 在第二个代码段中访问变量时,您应该锁定在第一个代码段中操作变量时锁定的同一个对象。