我创建了一个应用程序,其中包含一些使用计时器定期更新的数据。该类还包含一些将数据传递给另一个类的公共函数。以下是它的外观:
private void OnTimer(object sender, ElapsedEventArgs status)
{
GetNewData();
}
public void GetData(ref List<double> data, int index)
{
if (index < m_data.Length)
{
data = new List<double>(m_data[index]);
}
else
{
data = new List<double>();
}
}
目前,我没有任何保护措施来确保GetData函数在修改时没有访问数据。 你能指出我保护共享数据的最佳方法吗?
答案 0 :(得分:1)
您可以锁定代码。每个线程都会在你的lock语句中等待,然后进入你的新数据创建:
private void OnTimer(object sender, ElapsedEventArgs status)
{
GetNewData();
}
object lockCheck = new object();
public void GetData(ref List<double> data, int index)
{
lock(lockCheck)
{
if (index < m_data.Length)
{
data = new List<double>(m_data[index]);
}
else
{
data = new List<double>();
}
}
}
答案 1 :(得分:1)
您对如何更新数据并不太具体。如果您的GetNewData
方法完全取代m_data
成员,则根本不需要锁定。考虑一下:
// this is the shared data
SomeDataType m_data;
// Method that reads the data
public void GetData(ref List<double> data, int index)
{
// get a reference to the existing data
var localData = m_data;
// only work with the localData reference here
}
private void OnTimer(object sender, ElapsedEventArgs status)
{
GetNewData();
}
现在,让您的GetNewData
方法使用局部变量加载数据。加载完毕后,替换m_data
参考:
private void GetNewData()
{
var localData = /* create the data here */
// replace the reference
m_data = localData;
}
使用这种技术,get方法和计时器无法相互干扰。如果在getter运行时调用GetNewData
,则没有问题,因为getter正在使用本地引用。
唯一可能的问题是,如果在GetNewData
运行时调用getter,则返回的值将来自旧列表。也就是说,可能是陈旧的数据。这是否是一个问题,真的是由你来决定。
答案 2 :(得分:0)
集合专门旨在用于多个线程以相互提供数据。您可以使用BlockingCollection
,它是ConcurrentQueue
的包装器,允许您的计时器生成数据,将其添加到队列,然后让代码从其他地方读取该队列并处理结果。然后BlockingCollection
将负责线程之间的所有同步。