(Expert question) How to make this thread-safe?

B

BoloBaby

All,

I believe I am having a threading problem. Class "BELights" is part of a
larger DLL that is used by my main application. A user control (of type
BESeat) within the main application raises an event and attempts to execute
the "StartTiming" method of BELights. The method does not execute which
leads me to believe that BELights is not thread-safe. (Or is it the user
control that is not thread safe?)

When an event fires for "mBECardReaderManager" - an object created by a
third DLL and used by the main application - the handler correctly executes
the "StartTiming" method of BELights. There doesn't seem to be any
threading issue in that part of the program, only between the user control
and BELights.

I've Googled this problem many times over and can't seem to find an answer
that makes any sense to me, therefore I'll ask here. How do I make BELights
thread-safe so that the desired method executes properly.

"Simplified" sample code follows with the relevant parts included.

'*****
'Pared down version of collection class - assume it is much more complicated
but that these are the relevant parts
'BELights is located in BEDIO.dll
'*****

Public Class BELights
Inherits CollectionBase

Public Event TimesUp(ByVal LightNumber As Integer)

Public Sub StartTiming(ByVal LightNumber As Integer, ByVal Duration As
Integer)
Dim pBELight As BELight
pBELight = list.Item(LightNumber - 1)
pBELight.StartTiming(Duration)
End Sub

Public Sub New()
Dim intCount As Integer
Dim pBELight As BELight
'add the lights
For intCount = 1 To 14
pBELight = New BELight
'add handlers for the two BELight events
AddHandler pBELight.LightChanged, AddressOf LightChanged
AddHandler pBELight.TimesUp, AddressOf LightTimesUp
pBELight.LightNumber = intCount
pBELight.Reset()
list.Add(pBELight)
Next
End Sub

Private Sub LightTimesUp(ByVal LightNumber As Integer)
RaiseEvent TimesUp(LightNumber)
End Sub

Private Sub LightChanged(ByVal LightNumber As Integer, ByVal LightStatus
As BELight.BELightStatus)
'do some irrelevant code...
End Sub

End Class

'*****
'BELights is accessed through this class which is included in BEDIO.dll
'Again, this class is simplified
'*****

Public Class BEDIO
Private WithEvents mBELights As New BELights

Public Event TimesUp(ByVal LightNumber As Integer)

Public ReadOnly Property Lights() As BELights
Get
Return mBELights
End Get
End Property

Private Sub mBELights_TimesUp(ByVal LightNumber As Integer) Handles
mBELights.TimesUp
RaiseEvent TimesUp(LightNumber)
End Sub

End Class

'*****
'My main application contains this code
'frmMain is the startup object
'*****

Public Class frmMain
Inherits System.Windows.Forms.Form

'****This form contains an instance of the user control type BESeat,
known as Seat1
'****Seat1 fires an event called "ManuallyStartTime" (see below for
handler)
'****ManuallyStartTime is fired as the result of the user selecting an
option from a ContextMenu
'****that is associated with Seat1

'****BECardReaderManager comes from BELib.dll
Public WithEvents mBECardReaderManager As New BECardReaderManager
Public WithEvents mBEDIO As New BEDIO.BEDIO

'****No threading problem in the event handler for mBECardReaderManager
'****mBEDIO.Lights.StartTiming works fine (the timing light comes on)
Private Sub mBECardReaderManager_BECardInserted(ByVal eCardReaderName As
String, ByVal eCardReaderNumber As Integer, ByVal eCardID As String) Handles
mBECardReaderManager.BECardInserted
mBEDIO.Lights.StartTiming(eCardReaderNumber, 240)
End Sub

'>>>>>mBEDIO.Lights.StartTiming does not work here<<<<<
'****(This sub actually handles many more SeatX.ManuallyStartTime events
than just the one shown)
Private Sub ManuallyStartTime(ByVal Seat As BESeat) Handles
Seat1.ManuallyStartTime
'Seat is a passed instance of Seat1, the object that fires the event
mBEDIO.Lights.StartTiming(Seat.LightNumber, 240)
End Sub

End Class


WHEW...

OK, if you made it that far, you are a real trooper. Also, I'd hope that my
problem is fairly clear. I don't have experience in making stuff like this
thread-safe... maybe you do. Any help would be greatly appreciated.

Thanks,

Gardner
 
A

Armin Zingler

BoloBaby said:
All,

I believe I am having a threading problem. Class "BELights" is part
of a larger DLL that is used by my main application. A user control
(of type BESeat) within the main application raises an event and
attempts to execute the "StartTiming" method of BELights. The method
does not execute which leads me to believe that BELights is not
thread-safe. (Or is it the user control that is not thread safe?)

When an event fires for "mBECardReaderManager" - an object created by
a third DLL and used by the main application - the handler correctly
executes the "StartTiming" method of BELights. There doesn't seem to
be any threading issue in that part of the program, only between the
user control and BELights.

I've Googled this problem many times over and can't seem to find an
answer that makes any sense to me, therefore I'll ask here. How do I
make BELights thread-safe so that the desired method executes
properly.

"Simplified" sample code follows with the relevant parts included.
[...]

I've been reading the code and tried to understand, but my main question
remains: Where do you create and start a thread?? I don't see it.


--
Armin

How to quote and why:
http://www.plig.net/nnq/nquote.html
http://www.netmeister.org/news/learn2quote.html
 
B

BoloBaby

I've been reading the code and tried to understand, but my main question
remains: Where do you create and start a thread?? I don't see it.

Armin,

I don't explicitly start any additional threads. I've encountered a
similiar instance like this in the past where controls and classes from
different DLLs/EXEs seem to operate in their own, non-explicitly created
threads.

In fact, in another part of this application (a different EXE), I was adding
and removing user controls to a panel object. While doing so, I noticed
that the Panel.Controls.Add and Panel.Controls.Remove methods were both not
firing. I checked Panel.InvokeRequired and - sure enough - it was "True."

There isn't a lick of multi-threading code anywhere in my application, and
yet I seem to be having this problem. Perhaps each new instance of the user
control I am using creates a new thread for itself.

I can't figure any other reason for mBEDIO.Lights.StartTiming to NOT run
except that it is not thread-safe. No exceptions are being thrown, the
method simply fails to execute. As indicated in the sample code, the method
works just fine when called during a different event handler.
Seat1.InvokeRequired returns false, so I assume the problem is in BELights.

Maybe I'm confused. Is there some other reason why this method could
possibly fail to execute without any exceptions being thrown? The
parameters being passed to the method are exactly the same...

Gardner
 
B

BoloBaby

Actually, now that I think about it, the BELight object does access a
digital i/o card's driver when StartTiming is called. Perhaps the card's
driver is somehow getting the whole process on a different thread...
 

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