Locking memory and multiple timers?

G

Guest

I have an application that uses mulitple timers. Each of the timer event
handlers manipulate a common array of data.
I'm getting Null refererance errors - should I put a lock on the array when
I change a value?
As well, should I lock the array when I only want to read a value?
 
J

Jon Skeet [C# MVP]

FredC said:
I have an application that uses mulitple timers. Each of the timer event
handlers manipulate a common array of data.
I'm getting Null refererance errors - should I put a lock on the array when
I change a value?

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

In general though, yes - you need to obtain a lock (on something, see
below) if you're going to access/change shared data.
As well, should I lock the array when I only want to read a value?

I wouldn't lock the array, but a separate locking object. See
http://www.pobox.com/~skeet/csharp/threads/lockchoice.shtml
 
B

Ben Voigt

FredC said:
I have an application that uses mulitple timers. Each of the timer event
handlers manipulate a common array of data.

Which Timer class are you using?

There's System.Windows.Forms.Timer, System.Threading.Timer,
System.Timers.Timer -- and they all act very different!

System.Windows.Forms.Timer will pass WM_TIMER, causing your handler to be
called on the main thread in between user actions. They will be serialized,
and locking does nothing if you're not pumping messages (think
Application.DoEvents) during a callback, and if you are -- deadlock with
non-recursive locks, and data corruption with recursive locks. But if you
prevent re-entrancy by not pumping messages during the timer processing,
everything is much simpler.

The others will create background worker threads. Locking is applicable
here.
I'm getting Null refererance errors - should I put a lock on the array
when
I change a value?
As well, should I lock the array when I only want to read a value?

If you're resizing the array, you must lock writes. Otherwise locks
shouldn't be necessary. Locking reads shouldn't be needed, although after a
resize your reads could be accessing an old copy for an extended length of
time.
 
J

Jon Skeet [C# MVP]

If you're resizing the array, you must lock writes.

Could you explain exactly what you mean by that?
Otherwise locks
shouldn't be necessary. Locking reads shouldn't be needed, although after a
resize your reads could be accessing an old copy for an extended length of
time.

Or they could just not "see" some of the writes at all. I tend to want
to know that the data I'm accessing is the most recent version...
 
B

Ben Voigt

Jon Skeet said:
Could you explain exactly what you mean by that?

A .NET array is ultimately pretty similar to a SAFEARRAY, it's a pointer to
a block of data and some accompanying size information. If you need to grow
the array (done automatically by ArrayList or List<T>, or explicitly by
Array.Resize()), you end up with a pointer to an entirely different array,
and the runtime copies the data into the new block in the process. But you
could end up with still having pointers to the old block in other threads.
Or they could just not "see" some of the writes at all. I tend to want
to know that the data I'm accessing is the most recent version...

As long as you aren't doing anything that replaces the array pointer, all
threads will be working in the same memory area. However, the optimizing
compiler could decide to cache data in a register... you need memory fences
if "apparent" order of memory access is important.
 
J

Jon Skeet [C# MVP]

Ben Voigt said:
A .NET array is ultimately pretty similar to a SAFEARRAY, it's a pointer to
a block of data and some accompanying size information. If you need to grow
the array (done automatically by ArrayList or List<T>, or explicitly by
Array.Resize()), you end up with a pointer to an entirely different array,
and the runtime copies the data into the new block in the process. But you
could end up with still having pointers to the old block in other threads.

Absolutely - and I see what you mean about locking for writes now, in
that you don't want one thread writing to the old array when it's been
recreated.
As long as you aren't doing anything that replaces the array pointer, all
threads will be working in the same memory area. However, the optimizing
compiler could decide to cache data in a register... you need memory fences
if "apparent" order of memory access is important.

Exactly. That's the point I was getting at.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top