0

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?

1
  • 2
    Have a look at the 'lock'-statement Commented May 6, 2014 at 13:31

3 Answers 3

1

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>();
    }
}
}
Sign up to request clarification or add additional context in comments.

4 Comments

I have looked a bit on the lock and I was wondering if it is better to put it in the Get function or in the timer thread?
I can't see your whole code but if you are triggering your OnTimer by threads then it would make sense to put the lock there. From here what I see is OnTimer is only calling GetNewData method. So in this case it would be better to put your code inside your GetData method, because that's where your lock has to put your threads in queue.
If you're going to use a lock, you need to use it in both places: in the getter and in the setter.
Well I didn't put the all code because it is quite long and it modifies several variables. And in fact I have several public functions to retrieve each data. I will try to put the lock in the timer.
1

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.