在线程和类之间共享变量

时间:2014-05-06 13:28:09

标签: c# multithreading

我创建了一个应用程序,其中包含一些使用计时器定期更新的数据。该类还包含一些将数据传递给另一个类的公共函数。以下是它的外观:

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函数在修改时没有访问数据。 你能指出我保护共享数据的最佳方法吗?

3 个答案:

答案 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将负责线程之间的所有同步。