System.Timers.Timer()

SERVER: The .exe is running on a Windows XP server.

DEVELOPMENT: Visual Studio 2005 Standard Edition

LANGUAGE: VB.Net 2005

ERROR RECIEVED: The wait completed due to an abandoned mutex

ERROR DESCRIPTION:

I'm using a System.Timers.Timer() object inside a windows form. The application is started each day in the morning around 7:30. It runs smoothly all day, but errors out(the log shows it is at 7:31AM, which would be the call to the IfxRealTimeAppointmentLoad routine). Basically the application calls the IfxLoadTodaysAppointment() once and then continually calls the IfxRealTimeAppointmentLoad() routine every 5 seconds. What I'm trying to do is have the application stop calling both routines at 12:00AM and then start the entire process over at 7:00AM. When I check the logs in the morning, I'm seeing the following error:

The wait completed due to an abandoned mutex

I'm not sure what is causing this. Please see my questions and code below.

QUESTIONS:

Is it ok to stop/start the timer within the handler event?

Is it ok to create a thread inside a timer? (This is to pass progress back to the form's progress bar)

Is it ok to pause for a long period of time?

CODE:

PrivateSub Timer1_Elapsed(ByVal senderAs System.Object,ByVal eAs System.Timers.ElapsedEventArgs)

Dim strErrorWindowHeaderAsString

strErrorWindowHeader ="Timer1_Elapsed"

Dim CurrentDateTimeAs DateTime = e.SignalTime.ToString()

Dim AmPmAsString = CurrentDateTime.ToString.Substring(CurrentDateTime.ToString.Length - 2, 2)

Try

Timer1.Stop()

'12:00AM - 6:59AM servers may shut down, do nothing.

'7:00AM - 7:30AM Load Once Todays Appointments.

'7:31AM- 11:59AM Look for updates.

If currentLoadDate =NothingThen

IfxLoadTodaysAppointments()

GoTo CatAndFin

EndIf

If (AmPm ="AM")Then

'12:00-12:59 AM

If CurrentDateTime.Hour = 12Then

GoTo CatAndFin

EndIf

'1:00-6:59 AM

If CurrentDateTime.Hour >= 1And CurrentDateTime.Hour <= 6Then

GoTo CatAndFin

EndIf

'7:00-7:30 AM

If CurrentDateTime.Hour = 7Then

If CurrentDateTime.Minute <= 30Then

If (currentLoadDate.Day.ToString <> CurrentDateTime.Day.ToString)Then

IfxLoadTodaysAppointments()

EndIf

GoTo CatAndFin

EndIf

EndIf

EndIf

'7:31 AM THROUGH 11:59 PM

IfxRealTimeAppointmentLoad()

CatAndFin:

Me.ProgressThread =New Thread(New ThreadStart(AddressOfMe.ThreadProcSafe))

Me.ProgressThread.Start()

Catch exAs Exception

LogError(strErrorWindowHeader & vbNewLine &"ERROR: " & ex.Message & vbNewLine)

Finally

ProgressThread =Nothing

strErrorWindowHeader =Nothing

CurrentDateTime =Nothing

AmPm =Nothing

Timer1.Start()

EndTry

EndSub

Thanks for your help

[7715 byte] By [Sql4088] at [2007-12-22]
# 1

Although this code is a bit dated (you've got GOTOs!), there doesn't appear to be anything outright wrong with it (your datetime comparisons could be improved/simplified).

The answer to all three of your questions is "yes". All of those are ok if done properly.

As far as the specific error goes, I don't see any wait operations being called... This is probably a threading issue; you should post the code for Me.ThreadProcSafe... There may be unsafe multithreading calls taking place from there. The problem might also be in your Ifx method calls.

It also appears that your 7:00-7:30 code runs repeatedly through this time period; if it should not run more than once, this could also cause a problem (depending on what those ifx method calls do).

rkimble at 2007-8-30 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 2

Great insight.

It most definatly is a threading issue.

I will take a look at both the IFX routines for any loose code. I might be missing something there.

I checked the ThreadProcSafe and the code looks correct. The code i used is from a microsoft tutorial on threading. My code is below if you want to take a peak.

I checked the 7:00AM-7:30AM code and it appears to be O.K.. CurrentLoadDate will be set to CurrentDate when it calls the IfxLoadTodaysAppointments routine.

QUESTIONS:

Your concern "I don't see any wait operations being called...". Can you please be more specific. I do not know what you mean by a wait operation. Is this for the timer? Is this for the thread I created for the progressbar?

Private Sub ThreadProcSafe()

Me.SetProgress(1)

End Sub

Private Sub SetProgress(ByVal Value As Integer)

Dim strErrorWindowHeader As String

strErrorWindowHeader = "SetProgress"

Try

' InvokeRequired required compares the thread ID of the

' calling thread to the thread ID of the creating thread.

' If these threads are different, it returns true.

If Me.ProgressBar1.InvokeRequired Then

Dim d As New SetProgressCallback(AddressOf SetProgress)

Me.Invoke(d, New Object() {value})

Else

If Me.ProgressBar1.Value + value > Me.ProgressBar1.Maximum Then

Me.ProgressBar1.Value = 0

End If

Me.ProgressBar1.Value = Me.ProgressBar1.Value + value

End If

Catch ex As Exception

LogError(strErrorWindowHeader & vbNewLine & "ERROR: " & ex.Message & vbNewLine)

Finally

strErrorWindowHeader = Nothing

End Try

End Sub

Thanks for your help so far.

Sql4088 at 2007-8-30 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 3

What I mean by wait operations are any methods that cause a thread to enter a waiting state.

You might want to look at: http://msdn2.microsoft.com/en-us/library/system.threading.abandonedmutexexception.aspx

This gives some detail on your exception and mentions that this is the result of a serious progamming error - though the error may be hard to track down. You'll probably need to set your system clock to a time that will cause the error to occur and then step through the code in the debugger to determine exactly where the mutex is being abandonded at.

Alternately, the MSDN documentation linked above states that your app can handle and continue past this error by just verifing that any data structures used by the thread are still valid.

Since this error is caused (presumably) by a thread exiting incorrectly, you should look at your code for scenarios that may cause a thread to terminate unexpectedly (this is just a guess for a starting point).

Lastly, I'd have to guess that this is a VS05 application (this exception is new to framework 2.0) so why not use the BackgroundWorker component instead of implementing your own multithreading? Using the BackgroundWorker usually eliminates all of the headaches associated with multithreading.... Just a thought.

rkimble at 2007-8-30 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 4

When a timer is created, it is on its own thread. The only way to pass data back to the form is to create another thread and pass data through a delegates routine. I actually commented all that code out in a test and the application still errored out. This is the only thread that I created.

I'm not sure what is going on but I'm going to redesign both the IFX routines. Thanks for your help so far, it has been greatly appreciated.

Sql4088 at 2007-8-30 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 5

I'm not sure what you mean here...

The Timer Component itself does not exist on a seperate thread from the one that created it. Now, the Timer component does run a seperate thread to handle the ticking of the timer, but the Elapsed/Tick event is already raised using delegates to that it occurs in the context of the thread that created the Timer component. So if the Timer and Form are both owned by the same thread, you don't have to do anything special to interact with the Form from the Timer.Elapsed event handler.

This is evident by the fact that the code running the the Elapsed event blocks the application. Also, if the timer's interval is set to 10ms, but the elapsed event handler takes 1000ms to complete then the event is only handled once every 1000ms - despite the 10ms interval.

rkimble at 2007-8-30 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 6

This is fun.

The timer was initially created in code and I was not able to pass data back to the form on the same thread.

I deleted the code that created the timer and added a new timer to the form from the toolbox. I'm now able to pass progress without creating a different thread........

This is wacky and I'm getting really fed up. Maybe it's time to start the application over.

Sql4088 at 2007-8-30 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 7
I'm using an Informix connection inside both my custom IFX routines. When I open the connection with the IfxConnection.Open() method it is causing the Abandoned Mutex Error. Thank you for your help, you were a big help.
Sql4088 at 2007-8-30 > top of Msdn Tech,Visual Basic,Visual Basic Language...