Threading event handler problem...

mandelbrot

Centurion
Joined
Jul 1, 2005
Messages
194
Location
UK North East
Hi Everyone,


I've got a small problem with an event that's raised by a threaded component that I've written. The component simply monitors whether a PDA is attached or removed from its cradle and then whether files are added or removed from the folder that is the common link between both PDA and PC.

The Event is triggered as you would expect, but the handler behaves in an extremely odd manner - it doesn't seem to execute, but certain calls based within the handler do!

I have turned the CheckForIllegalCrossThreadCalls property off for the handling form, but don't see why this should cause any problems.


Paul.
 
Can you post the portion of code to see what is going on?

I have been working with threads as I monitor test equipment, one thing I found to do before starting the thread is make the IsBackground to true because my thread would just quit all of a sudden.
 
Hi techman,


Visual Basic:
                _Djinni = New Threading.Thread(AddressOf Monitor)
                _Djinni.IsBackground = True
                _Djinni.Start()
This is the start of the threading op. It's defined earlier in the code as a class level variable (for reference by the other methods and properties within).

Visual Basic:
    Private Sub Monitor()
        'Set the starting state of the old connection...
        Dim oldConnect As PDAConnectState = PDAConnectState.NotPresent
        Dim oldFiles() As String = Nothing
        Dim newFiles() As String = Nothing
        'Flags to make sure that certain events are only raised once...
        Dim flagDisconnect As Boolean = False
        Dim flagTimeout As Boolean = False
        Dim flagWaitfail As Boolean = False
        'Only run the monitor loop while the class is not disposed and the thread is running...
        Do While Not isDisposed And DjinniState <> (Threading.ThreadState.Stopped Or Threading.ThreadState.StopRequested)
            'Check the current state of the PDA...
            _ConnectState = PDA.IsConnected()
            'Respond appropriately to the connection state...
            Select Case _ConnectState
                Case PDAConnectState.Connected
                    'Set the flags...
                    flagDisconnect = False
                    flagWaitfail = False
                    flagTimeout = False
                    'Check to see if this is a new connection...
                    If _ConnectState <> oldConnect Then
                        _ActivePDA = New PDA
                        _ActivePDA.GetPDADetail()
                        ClearShare()
                        RaiseEvent PDAConnected()
                        'We can wait until the next time round the loop to receive the connection file.
                    Else
                        'Check to see if the target path actually exists - if it doesn't then create it...
                        If Not IO.Directory.Exists(_ActivePDA.PdaPcFileSharePath) Then
                            IO.Directory.CreateDirectory(_ActivePDA.PdaPcFileSharePath)
                        End If
                        'Check to see if a file's been dropped...
                        newFiles = IO.Directory.GetFiles(_ActivePDA.PdaPcFileSharePath)
                        Array.Sort(newFiles)
                        If Not oldFiles Is Nothing Then
                            Array.Sort(oldFiles)
                        End If
                        'Loop through and see if they're different...
                        For loopCounter As Int32 = 0 To newFiles.GetUpperBound(0)
                            Dim newIndex As Int32 = Array.BinarySearch(oldFiles, newFiles(loopCounter))
                            If newIndex < 0 Then
                                'This is a new file, so let's process it...
                                ProcessFile(newFiles(newIndex))
                            End If
                        Next loopCounter
                    End If
                Case PDAConnectState.NotPresent
                    'Raise that the event has been raised...
                    If Not flagDisconnect Then
                        RaiseEvent PDADisconnected()
                        flagDisconnect = True
                    End If
                Case PDAConnectState.TimeOut
                    'Note that the event has been raised...
                    If Not flagTimeout Then
                        RaiseEvent PDATimedOut()
                        flagTimeout = True
                    End If
                Case PDAConnectState.WaitFail
                    'Note that the event has been raised...
                    If Not flagWaitfail Then
                        RaiseEvent PDAWaitFailed()
                        flagWaitfail = True
                    End If
            End Select
            oldConnect = _ConnectState
            'Go back to sleep for a while...
            Threading.Thread.Sleep(_TickDelay)
        Loop
    End Sub
This is the main body of the process - it simply monitors a folder to see if files are being dumped into it. I know that I can use a FileMonitor here, but I've written it like this for ease of portability between the PDA and PC.

Visual Basic:
    'PDAConnected() and PDADisconnected  -  PDA docking state has changed
    Private Sub pdaMon_PDAConnectState() Handles pdaMon.PDADisconnected, pdaMon.PDAConnected
        If Me.InvokeRequired Then
            [color=red]Util.NOP()[/color]
        End If
        'We only want to do this if the PDA monitor has been initialised properly...
        If Not pdaMon Is Nothing AndAlso Not [color=red]pdaMon.IsInitialising[/color] Then
            'Notify the user of the state change...
            Dim resourceIcon As Int32 = 0
            If pdaMon.ConnectState = PDAConnectState.Connected Then
                resourceIcon = iconPdaOn
            Else
                resourceIcon = iconPdaOff
            End If
            'Display the state in the status bar at the bottom of the screen...
            stpnlPda.Icon = Icon.FromHandle(DirectCast(icons16.Images(resourceIcon), Bitmap).GetHicon)
        End If
    End Sub
This is the final part of the jigsaw.

It all works fine - this code runs through and raises all of the events as it should. The problem seems to be when a PDA is plugged in or removed - it's supposed to display an icon in the status bar on the main form, but doesn't!!!

The PDA monitoring class is instantiated properly within the MDI form that employs its use, and is defined WithEvents. All handlers are defined properly, but, despite the fact that the events are raised by the Djinni code, the handlers do not appear to work. The odd thing, however, is that some of the routines used within the handler appear to fire (those highlighted in red)... (?!!??!?!) :confused:

I've already made the change that you've suggested, but it hasn't appeared to alter the event situation.

Any light that you can shine on this would be extrmemely appreciated.

Paul.
 
I have a question, that you may have already done for debugging, did you put a breakpoint here
Code:
    stpnlPda.Icon = Icon.FromHandle(DirectCast(icons16.Images(resourceIcon), Bitmap).GetHicon)

to see if your code makes it to this point?

also something that sorta confused me for a sec was the [color]. It didn't highlight it is red, I just see the brackets.

Is the monitor sub in the MDI form? and is the pdaMon_PDAConnectState() sub in the same form or in the main form? If is is on the main for, you may want to make the sub Public sub. Not sure if this is correct, I am throwing out ideas as I am trying to read the code while looking over my shoulder for the boss:eek:
 
Hmmm...

LOL! Yes - the coreUtil.NOP should have been red, along with the pdaMon.IsInitialising!

The coreUtil.NOP() function is one of the most useful functions I've ever written - simplicity is always best - it does absolutely nothing! I use it as a breakpoint placeholder, so that I can test external conditions and values within the current function. As I said, though, the funny thing was that coreUtil.NOP() actually ran, but the icon on the form didn't change!!

No - the Monitor sub is in the class that handles the Djinni thread. This class is used to keep track of the PDA and files in the shared folder.

Yes - pdaMon_PDAConnectState() sub is in the formMainMDI class.


Paul.
 
Oops - forgot to answer the first bit of the thread there - I have tried putting breakpoints through-out the bits that aren't executing, but to no avail.
 
Good morning Techman,


Techman - you're a star, mate! That worked - the icon has now popped up at the bottom of the screen as it's supposed to...

I have no idea why, though - I don't understand why changing the scope of the subs should make it work or not work. Very odd! Any ideas?


Paul.
 
Glad I could help. The reason is that you have the subs in a different class/form. When you use private, that sub is only seen in that class. By making it public, this allows the other classes to see that sub. You can also use Friend. Friend allows the other classes in that project to see that sub, but no other applications(as in another exe application) can see that sub. Public will allow other applications to see it. Like in a DLL. Hope that made sense.

Take it easy,
Brian.
 
Yep - got that. I think that if I declare the actual pdaMon as friend that should achieve the same. I must admit I didn't think of that. All objects that go on a form are declared as Friend...

Thanks again Brian,
Paul.
 
Back
Top