Lock problems with System.Timers.Timer

B

Ben

Hello everybody

I got confused by this problem for which I don't have a logical explanation.
There is a Thread (ThreadA) which receives Events from another system thread
(ThreadS). ThreadA then adds a time stamp to the received event and adds it
to a event queue. This works well (therfore not shown here). The queue fills
up.
Then I used a timer to check every millisecond for new events in the queue
and send it to another thread (ThreadC). I included a lock statement on a
static object to ensure a critical section. But after some time (6 hours)
the timer stops.
I debugged it and found that i could even not restart the timer executing
m_EventTimer.Start().

What do I wrong? Why is the timer blocking?
Ok, perhaps, many events will be generated during the time the Timer_Elapsed
event happens. But the lock statement should do the job and not allow any
false Start() Stop() of the timer... What happens to the timer events which
have to wait? Does this anybody know?

Many thanks for tips
Ben



private void OnEventTimer_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
lock(m_EventTimerLockObject)
{
MyClass.personalMessage tmpPersMsg;
try
{
m_EventTimer.Stop();
//send all events which already occurred to the TAPI class for logging
while(m_Events.Count > 0)
{
lock(m_Events)
{
tmpPersMsg= (MyClass.personalMessage )m_Events[0];
m_Events.RemoveAt(0);
}
this.OnLineMessage(new PersonalMessageEventArgs(tmpPersMsg));
}
}
catch(Exception ex)
{
Logging.LogDatabase(150103, ex.Message, ex.StackTrace,
LogSeverityDB.Error, "PM.cs"); // Event timer raised an exception.
}
finally
{
m_EventTimer.Start();
}
}
}


Alternative (right now in test):
private void OnEventTimer_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
if(System.Threading.Monitor.TryEnter(m_EventTimerLockObject))
{
MyClass.personalMessage tmpPersMsg;
try
{
m_EventTimer.Stop();
//send all events which already occurred to the TAPI class for logging
while(m_Events.Count > 0)
{
lock(m_Events)
{
tmpPersMsg= (MyClass.personalMessage )m_Events[0];
m_Events.RemoveAt(0);
}
this.OnLineMessage(new PersonalMessageEventArgs(tmpPersMsg));
}
}
catch(Exception ex)
{
Logging.LogDatabase(150103, ex.Message, ex.StackTrace,
LogSeverityDB.Error, "PM.cs"); // Event timer raised an exception.
}
finally
{
System.Threading.Monitor.Exit(m_EventTimerLockObject);
m_EventTimer.Start();
}
}
}
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


Ben said:
Hello everybody

I got confused by this problem for which I don't have a logical
explanation.
There is a Thread (ThreadA) which receives Events from another system
thread (ThreadS).

How you assure than the event generated in thead S is handled in thread A ?
Then I used a timer to check every millisecond for new events in the queue
and send it to another thread (ThreadC).

In what thread is this?
I included a lock statement on a static object to ensure a critical
section. But after some time (6 hours) the timer stops.
I debugged it and found that i could even not restart the timer executing
m_EventTimer.Start().

What do I wrong? Why is the timer blocking?

I'm not very sure that you need all this, first of all why you need so many
threads doing part of the process?

In addition you don't have to use lock , simply use a Syncronized queue
(Queue.Syncronized ). then have one thread receive the message, prepare it
and place it in the queue.

Another thread will poll the queue at a regular interval and do any process.
 
B

Barry Kelly

Ben said:
I got confused by this problem for which I don't have a logical explanation.
There is a Thread (ThreadA) which receives Events from another system thread
(ThreadS). ThreadA then adds a time stamp to the received event and adds it
to a event queue. This works well (therfore not shown here). The queue fills
up.
Then I used a timer to check every millisecond for new events in the queue
and send it to another thread (ThreadC). I included a lock statement on a
static object to ensure a critical section. But after some time (6 hours)
the timer stops.
I debugged it and found that i could even not restart the timer executing
m_EventTimer.Start().

First, System.Timers.Timer is a component for UIs, you should check out
System.Threading.Timer for working with threading.

However, you are designing your architecture around polling - you
shouldn't do that. Google "producer consumer queue", I think you should
design your architecture in a different way.


-- Barry
 
B

Ben

Ignacio Machin ( .NET/ C# MVP ) said:
Hi,




How you assure than the event generated in thead S is handled in thread A
?

I checked it with the debugger. Breakpoints in the event receiving method
will be hit. It works and adds events to the queue. After some time I have
several thousand events in the queue which won't be processed because the
timer stops removing them from the queue. But here is the code in ThreadA
from the loop waiting for events from ThreadS:

// Get a event
Status = WaitForSingleObject(m_EventHandle, 200);
switch(Status)
{
case WaitForObjectsResults.WAIT_OBJECT_0: //a event is pending,
lineMsg = new Tapi.linemessage(0, 0, IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero);
if (GetTapiMessage(ref lineMsg) ==
Tapi2Lib.LineErrReturn.LINEERR_OK)
{
//Create Event
if(m_EventThreadIsSendingLineMessages)
{
AddEvent(lineMsg);
}
}
else
{
//No Msg (LINEERR_OPERATIONFAILED) or error
}
break;
case WaitForObjectsResults.WAIT_TIMEOUT: //Nothing to do
break;
default: //WaitForObjectsResults.WAIT_FAILED,
WaitForObjectsResults.WAIT_ABANDONED
//TODO : GetLastError();
break;
}

private void AddEvent(MyClass.personalMessage tmpPersMsg)
{
lock(m_Events)
{
m_Events.Insert(m_Events.Count, lineMsg);
}
}


In what thread is this?

A good question. I do not know. The code is in the same class. I think the
framework creates it's own thread for timers. But I am not sure. Does it
matter? I have a static object in the class on which I apply a lock.Then I
expect the code between the {} should be handled as a critical section from
whatever thread the method will be called. Perhaps this is a false
assumption?

I'm not very sure that you need all this, first of all why you need so
many threads doing part of the process?

In addition you don't have to use lock , simply use a Syncronized queue
(Queue.Syncronized ). then have one thread receive the message, prepare it
and place it in the queue.

Another thread will poll the queue at a regular interval and do any
process.

I will try this. Thanks.
 
B

Ben

Barry Kelly said:
First, System.Timers.Timer is a component for UIs, you should check out
System.Threading.Timer for working with threading.

However, you are designing your architecture around polling - you
shouldn't do that. Google "producer consumer queue", I think you should
design your architecture in a different way.


-- Barry

Ok I'll check the books. Thanks for the hint.
 

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