c# - 有没有一种安全的方法可以在线程之间快速交换数据?
问题描述
我正在设置一个从称重传感器读取数据的应用程序,并根据读取的数据实时中断电机的推力。必须从称重传感器获得高频读数。
我正在用 c# 编程,我决定使用单独的线程从称重传感器获取数据。我的问题是:如何以线程安全的方式使用线程中获取的数据?例如在图表中显示它们。
这是我调用以获取队列中的数据的线程。
Thread t = new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
while (save_in_queue)
{
Thread.Sleep(1);
if (queue.Count <= 1000)
{
queue.Enqueue(Frm_main.ComPh1.LeggiAnalogica(this.Address));
}
else
{
queue.Dequeue();
queue.Enqueue(Frm_main.ComPh1.LeggiAnalogica(this.Address));
}
}
});
t.Name = "Queue " + this.name;
t.Start();
这是我用来关联线程填充队列和主队列的方法
public void SetData(Queue<int> q)
{
this.data = q;
}
这是我在主应用程序中用于设置系列数据的计时器
private void timer1_Tick(object sender, EventArgs e)
{
List<int> dati = new List<int>();
lock (data)
{
dati = data.ToList();
}
grafico.Series[serie.Name].Points.Clear();
for (int x = 0; x < dati.Count; x++)
{
DataPoint pt = new DataPoint();
pt.XValue = x;
pt.YValues = new double[] { dati.ElementAt(x) };
grafico.Series[serie.Name].Points.Add(pt);
}
}
此代码不起作用,因为有时我在 dati = data.ToList(); 行上收到异常“集合已修改;枚举操作可能无法执行”;
形成我很清楚为什么我会收到此异常。但是如何解决呢?
我想避免使用太多的“锁”或太多的同步变量,以免降低采集性能,目前这非常好。
解决方案
您可能需要检查提供某些集合的线程安全实现的并发集合命名空间
System.Collections.Concurrent 命名空间提供了几个线程安全的集合类,当多个线程同时访问集合时,应该使用它们来代替 System.Collections 和 System.Collections.Generic 命名空间中的相应类型。
https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent
因此,您可以使用System.Collections.Concurrent.ConcurrentQueue而不是System.Collections.Queue来为您的问题提供无锁解决方案。