threads in .net and protecting shared variables

C

Claire

I was ok understanding threads in Delphi pre .net, but reading through a
reference book and comparing it to what help file says has confused me

A System.Threading.Timer thread in one class calls an event in a 2nd class
as follows (fast timer)

public void OnDriverSendResult(rackdetail RackDetail)
{
// Add new RackDetail to linked list and leave quickly
RackDetail.Previous = this.LastDetail;
if (this.LastDetail == null)
this.FirstDetail = RackDetail;
else
this.LastDetail.Next = RackDetail;
this.LastDetail = RackDetail;
}

In the 2nd class, I will have another system.threading.timer thread (slow
timer) that takes the linked list created by the first timer, processes the
data in it and posts it to a database.

private void ProcessList()
{
if (FirstDetail == null) return;

RackDetail Unprocessed = FirstDetail;
FirstDetail = null;
Processed = Process(Unprocessed);
Post(Processed);
}

How do I protect shared variables/objects in .net threads please. Some code
samples would be more useful to me in the first instance.

thanks
Claire
 
A

Ajay Kalra

Take a look at Monitor/Enter/Exit and lock(which uses Monitor
internally) to do synchronization. This is similar to Critical Section
in Win32. Another option to synchronize data is to use WaitHandle
derived classes, Mutex, ManualResetEvent and AutoResetEvents.
 
H

Helge Jensen

Ajay said:
Take a look at Monitor/Enter/Exit and lock(which uses Monitor
internally) to do synchronization. This is similar to Critical Section
in Win32. Another option to synchronize data is to use WaitHandle
derived classes, Mutex, ManualResetEvent and AutoResetEvents.

Or, use "lock", which is inherently exception-safe and (in this case)
pretty easy to read and understand.

You do realize that your OnDriverSendResult is not re-entrant -- even on
it's own?

You seem to be using a self-implemented linked list, why not use one of
the supplied data-structures in .NET?

BTW: this is the classic producer/consumer problem.

An easy solution, which should perform very well too, is sketched below.

The AutoResetEvent below is entirely optional code, but usefull if you
have a dedicated thread for running ProcessList.

readonly IList Queue; // Use ArrayList or LinkedList or whatever
readonly AutoResetEvent QueueNotEmpty = new AutoResetEvent();
public void OnDriverSendResult(RackDetail detail) {
lock ( Queue ) {
Queue.Add(detail);
QueueNotEmpty.Set();
}
}

private static IList emptyList; // choose any empty list to init with
public void ProcessList() {
IList process;
QueueNotEmpty.WaitOne();
lock ( Queue ) {
if ( Queue.GetEnumerator().MoveNext() ) { // non-empty?
process = new ArrayList(l);
Queue.Clear();
} else {
process = emptyList;
}
foreach ( RackDetail detail in process )
Process(detail);
}
 

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