Threading and modules and sleep.

Gopher2011

Well-known member
Joined
Mar 3, 2011
Messages
111
Location
South England
Programming Experience
10+
Hi,

I have a frm_Main, which starts a thread. The thread then goes and calls a module, which has a thread.sleep() in it. This causes the mouse to freeze up while it sleeps, despite being called by the child thread. I thought this would have be on the thread time-slice? However it is causing my form to freeze for the sleep duration.


VB.NET:
Imports System.Threading.Thread
Imports System.ComponentModel

[COLOR="blue"]Public Class frm_Main[/COLOR]

   Public WithEvents T1_Thread As BackgroundWorker
     
   [COLOR="blue"]Public Sub New[/COLOR]()
      InitializeComponent()
      T1_Thread = New BackgroundWorker
      T1_Thread.WorkerReportsProgress = True
      T1_Thread.WorkerSupportsCancellation = True
   [COLOR="blue"]End Sub[/COLOR]

   [COLOR="blue"]Private Sub SS_C_Start_smi_Click[/COLOR](ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SS_C_Start_smi.Click
      T1_Thread.RunWorkerAsync()
    [COLOR="blue"]End Sub[/COLOR]
   
   [COLOR="blue"]Private Sub T1_Thread_DoWork[/COLOR](ByVal sender As System.Object, _
                               ByVal e As System.ComponentModel.DoWorkEventArgs) _
                               Handles T1_Thread.DoWork
      T1_Thread.ReportProgress(1)
      Thread.Sleep(2000)                                 'This is ok no lag
    [COLOR="blue"]End Sub[/COLOR]
   
   [COLOR="blue"]Private Sub NewThread1_ProgressChanged[/COLOR](ByVal sender As Object, _
                                ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
                                Handles T1_Thread.ProgressChanged
      RTU_Write(2500,"Test Message")               'This time causes lots of screen lag
   [COLOR="blue"]End Sub[/COLOR]

   [COLOR="blue"]Private Sub NewThread1_RunWorkerCompleted[/COLOR](ByVal sender As System.Object, _
                                ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
                                Handles T1_Thread.RunWorkerCompleted
   [COLOR="blue"]End Sub[/COLOR]
   
[COLOR="blue"]End Class[/COLOR]

And the Module Code

VB.NET:
[COLOR="blue"]Module RTU_Code[/COLOR]
   [COLOR="blue"]Public Function RTU_Write[/COLOR](ByRef SleepTime As Integer, ByVal Msg As String) As Integer
      frm_Main.SerialPort1.Write(Msg)
      System.Threading.Thread.Sleep(SleepTime)
   [COLOR="blue"]End Function[/COLOR]

[COLOR="blue"]End Module[/COLOR]

The problem is the form lags when its run, it becomes slow while the sleep is going on. Any Advice?
 
The thread then goes and calls a module, which has a thread.sleep() in it.
Nope, ProgressChanged event handler is called in UI thread.
 
When you call ReportProgress, it raises the ProgressChanged event on the UI thread. That means that the ProgressChanged event handler is executed on the UI thread. That's the whole point: DoWork is raised on a secondary thread and ProgressChanged and RunWorkerCompleted are raised on the UI thread. Why exactly are you calling Thread.Sleep in the RTU_Write function?
 
Hi, Thanks for the quick reply's.

I have a 'sleep' to give the serial port time to respond - I simplified the code example. It calls a write, and then responds a few millisecs later reading from the RTU (remote terminal unit). I need to sleep in order to wait for the serial port buffer to fill.

RTU_Write(2500,"Test Message") actually sends specific commands but I dont want to get into to much detail here.

a second or so later i execute

RTU_Read()
 
The "problem" of using modules is that all members there are implicitly Shared, which means you must make available any instance data to it beforehand. Instead of basing this on fields in the module, which breaks the OOP model, you should pass any instance data your shared method requires through method parameters. For example from an instance method in the form class you can access the instance of the SerialPort directly because that is where it belongs, but if you created a Shared method in the form class you could no longer do that. Exactly the same as for the module method you would either have to prepare a shared field to hold the reference to the SerialPort instance, or add a parameter to the method and pass the SerialPort instance as argument to it. An object instance has all information about itself, but no information about its surroundings unless it has been given that information. As opposed to shared members, that can be accessed as common for all instances, has inherently no information about any instances.
 
I've never actually used the SerialPort class myself but I think that you might be complicating things unnecessarily. The DataReceived event is raised on a secondary thread anyway, so there's no need for you to use multiple threads explicitly.
 
Back
Top