Link to home
Start Free TrialLog in
Avatar of ZhenyaT
ZhenyaT

asked on

Multithreading

I have a program that listens to MSMQ messages and preforms database updates depending on messages. I want to build a monitor program that would display the arrived message on a form and also provide the user with ability to click on the buttons on this form at ANY time (even when my component is listening for MSMQ messages. I assume I have to put this component in a separate thread from the monitor application. How do I do it? I need details explanation and possible links with examples.

Thank you
Avatar of CJ_S
CJ_S
Flag of Netherlands image

You can create an out-of-process component, which checks for the events. Then whenever the client application needs to be notified you use the an event.

Public Event MyEvent(...)

and raise it using
RaiseEvent MyEvent(the paramaters necessary)

Then in your client application you use something like:
Public WithEvents MyVar as COMPPROJECT.CLASSNAME

Private Sub MyVar_MyEvent(...)

End Sub


How to monitor the MSMQ messages I have no idea, but I suppose you can somehow retrieve them...no experience in that part)

regards,
CJ
Avatar of ZhenyaT
ZhenyaT

ASKER

CJ:

I have the MSMQ working and that's what ive done - an out-of-process component. Unfortunatelly it doesnt work! I must be doing something wrong. What happens is that as soon as the outofprocess component enters say a loop, my monitor client blocks! When I click on it, windows brings up a message with switch to and retry options.
What you need to do is make the out of process component return immediately when handling the event. I usually achieve this type of thing by using a timer which i set active in the event handler and then return from the call. Whatever happens in the timer event will not block your other components. I can provide you with a 'code only' timer (messing around with forms and control is risky in this type of component).

Francois.
Make it an ActiveX EXE... and connect to it using GetObject("", "BLAH.BLOEH")

Regards,
CJ
ASKER CERTIFIED SOLUTION
Avatar of Z_Beeblebrox
Z_Beeblebrox

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Here is an example of multithreading in VB. This program reads 3 text files on 3 different threads.  I added a project reference to Microsoft Scripting Runtime to use File System Objects to access the files.

Timers on forms are used to kick off the threads asynchronously so the files process at the same time.
A form is also used to identify the first time though, since main is automatically called every time
a thread is created.

Even though the threads in this example process the files "independently", any communication between threads is still syncronized via COM which reduces application responsiveness.  If you are interested I can post an example of communicating between threads outside of COM control but in that case you will have to ensure that your threads don't update variables simultaneously.  

VB 6 is not very friendly to multithreading applications.  

==============================================
' MainModule.bas

' ActiveX EXE Name = MTNF
' Startup Object = Sub Main
' Threading Model = Thread per Object
' Start Mode = Standalone
' !!! Must compile and run outside IDE !!!

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal

lpWindowName As String) As Long
Private frmMainThreadForm As MainThreadForm
Private Const PROC_CAPTION = "MTNF Main Thread Form"
Private Thread1  As ProcessFileObject

Sub Main()
  If 0 = FindWindow(vbNullString, PROC_CAPTION) Then
      'MsgBox "Main = " & Hex(App.ThreadID)
      Set frmMainThreadForm = New MainThreadForm ' create first form on pre-existing thread
      frmMainThreadForm.Caption = PROC_CAPTION
      Set frmMainThreadForm = Nothing 'don't need this reference, form loads itself and stays alive
until unloaded
  End If
End Sub

Public Sub CreateThreads()
 Set Thread1 = CreateObject("MTNF.ProcessFileObject")
 Thread1.ProcessFile "a.txt"
 '
 Set Thread1 = CreateObject("MTNF.ProcessFileObject")
 Thread1.ProcessFile "b.txt"
 '
 Set Thread1 = CreateObject("MTNF.ProcessFileObject")
 Thread1.ProcessFile "c.txt"
 Set Thread1 = Nothing
End Sub

Public Sub ReportRecordCount(FileName As String, RecCount As Long)
  MsgBox FileName & " contains " & CStr(RecCount) & " records. Reported by Thread " & Hex(App.ThreadID)
End Sub

==============================================
' MainThreadForm.frm

Private Sub Form_Initialize()
   Timer1.Interval = 100
End Sub

Private Sub Timer1_Timer()
  Timer1.Enabled = False
  CreateThreads
  Unload Me
End Sub

==============================================
' ProcessFileObject.cls

Private frmTimerForm As TimerForm
 
Private Sub Class_Initialize()
  'MsgBox "Worker = " & Hex(App.ThreadID)
End Sub

Public Sub ProcessFile(FileName As String)
  Set frmTimerForm = New TimerForm
  frmTimerForm.SetOwner Me
  frmTimerForm.StartTimer FileName
End Sub

Public Sub RecordCount(FileName As String)
  ' add project reference to Microsoft Scripting Runtime
  ' to use File System Objects
  Dim fso As New FileSystemObject
  Dim fil1 As File
  Dim ts As TextStream
  Set fil1 = fso.GetFile(FileName)
  Set ts = fil1.OpenAsTextStream(ForReading)
  ts.ReadAll
  ReportRecordCount FileName, ts.Line
  ts.Close
  Set frmTimerForm = Nothing
End Sub
==============================================
' TimerForm.frm

Private objOwner As ProcessFileObject
Private strFileName As String

Public Sub SetOwner(objRef As ProcessFileObject)
  Set objOwner = objRef
End Sub

Public Sub StartTimer(FileName As String)
  strFileName = FileName
  Timer1.Interval = 55
End Sub

Private Sub Timer1_Timer()
  Timer1.Enabled = False
  objOwner.RecordCount (strFileName)
  Set objOwner = Nothing
  Unload Me
End Sub
Avatar of ZhenyaT

ASKER

CJ:

I have the MSMQ working and that's what ive done - an out-of-process component. Unfortunatelly it doesnt work! I must be doing something wrong. What happens is that as soon as the outofprocess component enters say a loop, my monitor client blocks! When I click on it, windows brings up a message with switch to and retry options.
Avatar of ZhenyaT

ASKER

Cheers dude, awesome idea...dunno why I didn't think of it...

one thing you missed out is you need to receive the message every time it arrives and then reset the EnableNotification.

Thanks a lot.