[2008] Prevent cross-threading exceptions outside a class
I'm designing a class that makes use of threads. These threads sometimes fire events, and when these events are handled in a form(outside of the class), they cause cross-threading exceptions. Now of course I can solve this by using Invoke methods or delegates, but I wonder if I could code the class in such a way the problem is already solved inside the class, this would make the class way more user-friendly. I couldn't find any clear solution on the web, that's why I'm asking here. Any kind of documentation/tutorial/example on this subject is welcome :)
Re: [2008] Prevent cross-threading exceptions outside a class
yes you can. I ran into this sort of thing a long time back. What you can do is create a constructor for your class that accepts a System.ComponentModel.ISynchronizeInvoke parameter and pass that the form that is using the class.
for exmple
Code:
''' <summary>
''' Gets or sets the object to invoke to avoid illegal cross thread calls
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property SyncObject() As ISynchronizeInvoke
Get
Return Me._syncObject
End Get
Set(ByVal value As ISynchronizeInvoke)
Me._syncObject = value
End Set
End Property
Code:
''' <summary>
''' Create a new instance of the chatlog class
''' </summary>
''' <param name="iSyncObject">The object that will be invoked (this is used to avoid illegal cross thread
''' calls when updating controls on a form from the newline event)</param>
''' <remarks></remarks>
Public Sub New(ByVal iSyncObject As System.ComponentModel.ISynchronizeInvoke)
Me.SyncObject = iSyncObject
If Not Initialize() Then
MsgBox("Unable to initialize... FFXI must be running")
End If
End Sub
Then you can handle all of the possible cross thread calls in the class like so
Code:
''' <summary>
''' Function called from within the thread to call the newline event. If the SyncObject is set, it will check if InvokeRequired and do so if necessary
''' </summary>
''' <param name="iLineInfo"></param>
''' <remarks></remarks>
Protected Overridable Sub OnNewLine(ByVal iLineInfo As ChatLine)
If iLineInfo.MsgID > _firstLine Then
If Me.SyncObject IsNot Nothing AndAlso Me.SyncObject.InvokeRequired Then
Me.SyncObject.Invoke(New LineAdded(AddressOf OnNewLine), New Object() {iLineInfo})
Else
RaiseEvent NewLine(iLineInfo)
End If
End If
End Sub
And when creating an instance of the class you just pass the form that will be using it so as to prevent any cross thread calls.
Code:
Dim c As New ChatLog(Me)
Re: [2008] Prevent cross-threading exceptions outside a class
Hmm.. this is a very interesting little tip. I wonder what are the comparisons between this method and the use of delegates, in terms of reliability and speed?
Re: [2008] Prevent cross-threading exceptions outside a class
This uses delegates as well but you simply pass in the the form object so that you can invoke it from the class. I didn't put the delegate in my example as i figured he already knew to use a delegate.
My delegate is used here.
Code:
''' <summary>
''' Function called from within the thread to call the newline event. If the SyncObject is set, it will check if InvokeRequired and do so if necessary
''' </summary>
''' <param name="iLineInfo"></param>
''' <remarks></remarks>
Protected Overridable Sub OnNewLine(ByVal iLineInfo As ChatLine)
If iLineInfo.MsgID > _firstLine Then
If Me.SyncObject IsNot Nothing AndAlso Me.SyncObject.InvokeRequired Then
Me.SyncObject.Invoke(New LineAdded(AddressOf OnNewLine), New Object() {iLineInfo})
Else
RaiseEvent NewLine(iLineInfo)
End If
End If
End Sub
Re: [2008] Prevent cross-threading exceptions outside a class
FYI, the most common classes that implement this interface are the FileSystemWatcher and System.Timers.Timer (the other Timer that used to be in the VS.NET 2003 Toolbox). When you create a FileSystemWatcher or Timer in code, by default they will raise their events on a thread pool thread. When you add one to a form in the designer, that form is automatically assigned to their SynchronizingObject property and they will this raise their events on the thread that owns the form.