Reputation: 121
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
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
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
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