背景:最近在做一个多串口通讯相关的功能,发现返回的数据错乱。再次做个笔记以防之后做项目的时候再遇到这种情况。
设计构想:串口通讯这块封装成一个类,接收到数据后,把数据压入解析类中的队列中,解析类解析完一个数据就通过事件委托的方式把数据传递给串口类;主界面上订阅了串口发送数据的事件,来接收串口类返回的数据。主界面中new两个实例,接收数据,但从返回的情况,发现返回的数据存在错乱,不正确的。主要的是不小心把解析类中存储的byte[]数组变量定义为static变量。
下面就写一个简单的程序模拟程序。
调用的类对象
public class EventTest
{
Object eventLock = new object();
public event EventHandler<int> DataEvent;
public int result = 0;
public static int count = 0;
public EventTest(int type)
{
Task.Run(() =>
{
while (true)
{
lock (eventLock)
{
if (DataEvent != null)
{
count ++;
DataEvent(this, count);
}
System.Threading.Thread.Sleep(1000 * 5);
}
}
});
}
}
主程序调用代码
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
EventTest eventTest1;
EventTest eventTest2;
private void Button_Click3(object sender, RoutedEventArgs e)
{
eventTest1 = new EventTest(5);
eventTest1.DataEvent += EventTest1_DataEvent;
}
private void EventTest1_DataEvent(object sender, int e)
{
Console.WriteLine("接收到1" + "返回数据 " + e.ToString());
}
private void Button_Click4(object sender, RoutedEventArgs e)
{
eventTest2 = new EventTest(100);
eventTest2.DataEvent += EventTest2_DataEvent;
}
private void EventTest2_DataEvent(object sender, int e)
{
Console.WriteLine("接收到2" + "返回数据 " + e.ToString());
}
}
运行结果图如下,从截图可以看出,第二个按钮接收的返回并不是正确的,而是在第一个按钮count运算后再累加的结果。
当把 public static int count = 0;改写成 public int count = 0;时,即把count定义为动态变量,则结果就执行正常了。
下面就进行static变量相关的解析:
这个问题其实很简单,没带static的变量属于对象,带了static的变量属于类本身,每一个类对只应一个class,在这个class被加载时,系统会在堆内存中为它分配一个空间,但每一个类可以创建出它的多个实例(也就是对象),当你在创建对像时系统会为你的每一个对像在堆内存中分配空间,这些对象都保存了对类中static的一个引用,也就是说不管你创建多少个对像,它们都指向同一个static变量,尽管类的实例包含该类的所有实例字段的单独副本,但每个static字段只有一个副本。所以就会出现数据错乱的情况。
解决:把串口类以及串口类相关的解析类中的static变量全部改成动态变量后,就实现了多串口通讯的功能。
**************************************************************************************************************