Try Catch Finally doesn't work!!

lsacchetti

Member
Joined
Mar 23, 2010
Messages
6
Programming Experience
5-10
I've a class with a timer inside

VB.NET:
Private tt As New System.Timers.Timer()

This timer is enabled in the New() of the class

VB.NET:
            Try
                tt.AutoReset = True
                tt.Interval = TimerPlcMan 'about 100 ms
                AddHandler tt.Elapsed, AddressOf ReadPlcRes
                tt.Enabled = True
                _tmrWork = False
            Catch ex As Exception
                _LastError = ex.ToString
            End Try
The timer tick is managed by the function ReadPlcRes

VB.NET:
    Private Sub ReadPlcRes(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
        If _tmrWork Then
            Exit Sub
        End If
        _tmrWork = True

        Dim start As Date = Now()
        Dim lbuff(-1) As PlcMessageStruct
        Try        
            For Each cnn As IPlcConn In _listaConn
                Do While cnn.MessageCount > 0
                    Dim msg As PlcMessageStruct = cnn.GetMessage
                    If Not msg.Id Is Nothing Then
                        ReDim Preserve lbuff(lbuff.Count)
                        lbuff(lbuff.Count - 1) = msg
                    End If
                Loop
            Next
            If lbuff.Count > 0 Then RaiseEvent NewPlcMessages(lbuff)
        Catch ex As Exception
            _myLog.WriteEv("ReadPlcRes", LogCentralizer.LogType.logAlarms, ex.ToString)
        Finally
            _tmrWork = False
        End Try
    End Sub
My problem is: I'm in a try..catch..finally statement. I supposed that no matter what happen in the try section. But sometimes the thread blocks as he never get out from this routine (and of course he did it, I'm sure)

I'he tried also with no autoreset, putting tt.start in the Finally branch, but the result is the same.
Anyone experienced some like that? Any idea?
 
Last edited:
First up, did you set a breakpoint and follow your code? Second, use the code tags when using code - for readability.
 
1) sorry it's the first time this forum and I didn't think about it
2) of course i cannot (neither with Remote debug) cause it happens twice at week and the timer interval is about 100 ms...... The problem is that my software must work 7/7 & 24/24 with silly user....
 
Try putting a SyncLock around the Try/Catch/Finally

It would also be beneficial to step through the code and see what it does and where it goes.
 
Thanks. I'm looking for SyncLock. But this raise more questions for me:
1) help tell me that SyncLock works like Try ... Finally. Actually I don't trust too much in this ;)
2) I've also the variable _tmrWork to prevent multiple access
3) inside my code there are two critical points: 1) callilng another class (with cnn.getMessage) of mine in which I have a Sleep(3) instructions, and 2) a RaiseEvent instruction. How they could affect a SyncLock command?
4) what about the lock object? could it be helpful to me? which informations can I get from it
5) differences between SyncLock and ReaderWriterLockSlim?

Excuse for all the silly question, and thanks in advance
 
1)
SyncLock and Try/Catch do completely different things. Try/Catch is for error/exception handling where as SyncLock prevents two or more threads from running the same set of code at the same time (which produces unpredictable results), I'm assuming you know how to use Try/Catch and here's the description article from MS about SyncLock: SyncLock Statement

The reason I suggest putting a SyncLock around the entire Try/Catch (not replacing it) is because you have the timer set to a ridiculously short interval and since Timers run on a separate thread (meaning the Timer's interval counter isn't on your UI thread, only the Tick event is executed on the UI thread) that tick event could be raising before the previous tick event has had time to finish (if the computer's really busy doing other things, with a 100ms interval it's quite possible the tick events are stepping on each other) the SyncLock would prevent the stepping on each other situation from occurring.

I don't know if this is what's actually happening, it's just a guess.

2)
I'm not sure how _tmrWork would be playing into this, I'm assuming it's a boolean?

3)
It shouldn't effect anything, other than you'll have a pile of events to be processed if there's a 3 second wait in the SyncLock and the timer's set to 100ms (that means after the first tick has finished and exited the synclock there'll be 3,000 tick events waiting to be process, after the 2nd tick event there 5,999 waiting, after the 3rd there's 7,998, etc...

4)
Lock is the C# equivalent of VB.Net's SyncLock, so they're the same, just different languages.

5)
The ReaderWriterLockSlim was added in the 3.5 Framework and my clients are running the 2.0 Framework (2 of them have the 3.0 Framework, but for 2 clients I still just do all 2.0 FW development) so I haven't used it and if I get time I'll play with it, I'm not sure what benefits it offers.
 
In first thanks to you for youe answers.
1) of course Try/Catch/Finally is different. For this reason I was astonished when I readed that "SyncLock is similar to Try/Finally". About my timer interval, I have to make a very hard control on a plant so I have to poll each 100ms the plant state. I can ensure you that 100ms are enough for this work (I builded messages classes so I dont'have to waste time answering or managing), By the way, my first try to avoid this was with a not autoreset timer and calling tt.start in the finally branch. Results are the same :(

2) _tmrWork is a boolean. I set it to true entering in the timer_tick and set to false in Finally branch. So if I get two tick event the second is bypassed and I don't have a lot of event pending

3) Sleep(3) is a 3 milliseconds wait, not seconds. I stress my programs, but I'm not fool :) Who needs a timer each 100ms with a 3 seconds wait???

4) ok

5) maybe ReaderWriterLockSlim lock the code but SyncLock lock also the objects (and the variables) managed by the code?

Again thanks for the useful and pleasant discussion
 
It is similar to "Finally" (that is always executed) in that "the SyncLock block guarantees release of the lock, no matter how you exit the block". As such it is also similar to Using statement that will always dispose the used object ;)

Purpose of SyncLock is to only allow one thread to execute a code block at a time, other threads will block and wait to enter that block. It is the lockobject that evaluates this lock.

ReaderWriterLockSlim is more diverse, not only can it be used to synchronize access to multiple code blocks at the same time, but also to control the type of access. For example it will allow multiple threads to enter in read mode, while only one thread in exclusive write mode, this will ensure that some object is not changed while any thread is reading it, and that only one thread can change it at any time.
JB said:
meaning the Timer's interval counter isn't on your UI thread, only the Tick event is executed on the UI thread
lsacchetti is using Timers.Timer, and no SynchronizingObject, so Elapsed event is async and not tied to UI.
SyncLock would prevent the stepping on each other situation from occurring
But is can also cause threads stacking up in a wait pile.

lsacchetti, why are you using a Timer here at all? In effect you have a single tight(ly) loop polling for data. Unless I misunderstood this:
I've also the variable _tmrWork to prevent multiple access
You only added that to debug the problem? If so, it depends on if you have a benefit having multiple threads reading messages, the ReaderWriterLockSlim may provide you with better synchronization if you do.
 
Thanks you, I now have a word more. I did some try and I'm quite sure I understood SyncLock.
I think that main difference between SyncLock and ReaderWriterLockSlim is the following:
ReaderWriterLockSlim is useful to grant that only one thread can access to the code. But (i think) you cannot use it twice in you code so, if you have to protect a variable used in two timer (i.e.), it doesn't work.
SyncLock can be used (with the same lock object) in more points of the code (watching for the deadlocks of courses). So if you use it in all points where a variable if modified you can grant that no multiple access to the variable are done.

lsacchetti, why are you using a Timer here at all? In effect you have a single tight(ly) loop polling for data. Unless I misunderstood this:

Quote:
I've also the variable _tmrWork to prevent multiple access

You only added that to debug the problem? If so, it depends on if you have a benefit having multiple threads reading messages, the ReaderWriterLockSlim may provide you with better synchronization if you do.

If I have to pool datas for a db, or from a PLC, or from "extarnal source" I think I must use timer. I have no event I can use. So I must read each xxx ms.
As I said, at the beginning I used a not autoresetting timer, to be sure that two ticks cannot be done. When I start to have the problem, I tried with Autoreset=true. But, as JuggaloBrotha said, my timer is very short, so I putted the _tmrWork variable to manage multiple ticks without having a pile of it

At the last actually I'm try with no autoreset timer but with a (hope) use of synclock to protect better a variable that was in another class. The matter is that problem only occurs twice in a week.....
(by the way, using synclock I had to raise my timer to 150 ms.... :( :D )
 
I suggest that you dont try to process PLC messages with a timer directly. Use a BackgroundWorker to do the receiving, and a separate BackgroundWorker to do the processing. Use a Queue (Of T) to hold the messages for processing, rather than an array. Here's a rough example of how I would do it :-

VB.NET:
Option Explicit On
Option Strict On

Imports System.ComponentModel

Public Class Form1

    Private WithEvents tmrReceiveCheck As New Timer
    Private WithEvents bwMessageReceiver As New BackgroundWorker

    Private ReceivedMessageQueue As New Queue(Of String)

    Private WithEvents bwMessageProcessor As New BackgroundWorker

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        tmrReceiveCheck.Interval = 100
        tmrReceiveCheck.Enabled = True
        tmrReceiveCheck.Start()
    End Sub

    Private Sub tmrReceiveCheck_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrReceiveCheck.Tick
        If Not bwMessageReceiver.IsBusy Then
            bwMessageReceiver.RunWorkerAsync()
        End If

        If Not bwMessageProcessor.IsBusy AndAlso ReceivedMessageQueue.Count > 0 Then
            bwMessageProcessor.RunWorkerAsync()
        End If
    End Sub

    Private Sub bwMessageReceiver_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwMessageReceiver.DoWork
        For Each cnn As IPlcConn In _listaConn
            Do While cnn.MessageCount > 0
                Dim msg As PlcMessageStruct = cnn.GetMessage
                If Not msg.Id Is Nothing Then
                    ReceivedMessageQueue.Enqueue(msg)
                End If
            Loop
        Next
    End Sub

    Private ReceivedMessage As PlcMessageStruct
    Private Sub bwMessageProcessor_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwMessageProcessor.DoWork
        While ReceivedMessageQueue.Count > 0
            ReceivedMessage = ReceivedMessageQueue.Dequeue
            'process ReceivedMessage here
        End While
    End Sub

End Class
 
Thank you Inertial, but I didn't explained all because my original problem didn't affect the low level
Anyway, when I started my project I didn't know BackGroundWorker, and also this is not a solution (I think).
Just to give you an idea, the type IPlcConn it's an interface. Assemblies that inherits this interface has collections (made with hastables for various reasons) and their own timer to make polling and to manage it.
The code I shown it's an higher level that get PLC answers from the collection with a different thread (tt timer thread). So the low-level thread put in message with it own thread & timing, and the high-level thread get them.
In this way I have that the two thread are independent and PLC communications are not blocked by managing previuos messages.

Hope I explained. Anyway thanks.
 
Back
Top