diditexas
diditexas

Reputation: 121

sharing variables between thread and class

I have created an app with a class containing some data that are updated at a regular interval using a timer. This class also contains some public function to pass the data to another class. Here is how it looks:

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>();
    }
}

At the moment, I don't have any protection to assure that the function GetData is not accessing the data while it is been modified. Could you point me to the best way of protecting my shared data?

Upvotes: 0

Views: 2813

Answers (3)

Servy
Servy

Reputation: 203838

There are collections specifically designed to be used for multiple threads to provide data to each other. You can use a BlockingCollection, which is a wrapper for a ConcurrentQueue to allow your timer to generate data, add it to the queue, and then have code elsewhere reading from that queue and processing the results. The BlockingCollection will then be responsible for all synchronization between threads.

Upvotes: 0

Jim Mischel
Jim Mischel

Reputation: 134125

You're not too specific about how you're updating your data. If your GetNewData method completely replaces the m_data member, then there's no need for a lock at all. Consider this:

// 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();
}

Now, make your GetNewData method load the data using a local variable. Once it's all loaded, replace the m_data reference:

private void GetNewData()
{
    var localData = /* create the data here */

    // replace the reference
    m_data = localData;
}

Using this technique, there's no way for the get method and the timer to interfere with each other. If GetNewData is called while the getter is running, there's no problem because the getter is working with a local reference.

The only potential problem is that if the getter is called while GetNewData is running, then the value returned will be from the old list. That is, potentially stale data. Whether this is a problem is really a matter for you to decide.

Upvotes: 1

Bura Chuhadar
Bura Chuhadar

Reputation: 3751

You can put a lock on your code. Each thread will wait on your lock statement and then will go inside your new data creation:

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>();
    }
}
}

Upvotes: 1

Related Questions