Solved

Using 2 timer controls on one single form

Posted on 2009-07-10
7
341 Views
Last Modified: 2012-05-07
Hello,

I have a windows form in vb.net 2008. This form has one timer control. This Pc is connected to 2 hardware units. My form reads the data from these 2 hardware units via the serial port. I have set the timer interval to 5 seconds. So after the first 5 seconds, I send request to serial port "1" which means data for hardware unit 1 and then I read receiving data for hardware unit 1 and then after next 5 seconds, I send request to serial port as "2" which means data for hardware unit 2 and I read the receiving data for hardware unit 2 and again after 5 seconds for hardware unit 1 and so on.

Now the client has suggested changes. He wants that I send request for hadware unit 1 after 5 seconds and the request for hardware unit 2 after 30 seconds. But I found that to implement this, I need to keep changing the timer interval after reading the data from serial port and this hangs the PC.

Hence now my question is:
1. Can I use two timer controls on one form with two different timer intervals?

2. If the above is not possible, then can I use two forms with two timer controls - one on each form with different timer internvals? The issue here would be that once I open the serial port in form 1, it may not allow me to open the port in form 2 as the serial port would be in use in form 1.

Any suggestions/solutions?

Regards,
MI
0
Comment
Question by:vj_mi
  • 4
  • 3
7 Comments
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 24829586
Yes, it it possible to use multiple Timers on the same Form but...

There are two ways to interpret your description.

Do you want:
5 secs --> Port 1
30 secs --> Port 2
5 secs --> Port 1
30 secs --? Port 2
etc...

Or?
5 secs --> Port 1
5 secs --> Port 1
5 secs --> Port 1
5 secs --> Port 1
5 secs --> Port 1
5 secs -->  Port 2
(repeat entire sequence)...

I think you want the latter?

I recommend ditching the Timer controls, though, and replacing them with BackgroundWorker controls.

Use SyncLock to prevent them from trying to access the serial port at the same time.

Here is a simplified example:
Public Class Form1
 
    Private PortLock As New Object
    Private WithEvents bgw1 As New System.ComponentModel.BackgroundWorker
    Private WithEvents bgw2 As New System.ComponentModel.BackgroundWorker
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        bgw1.WorkerReportsProgress = True
        bgw2.WorkerReportsProgress = True
        bgw1.RunWorkerAsync()
        bgw2.RunWorkerAsync()
    End Sub
 
    Private Sub bgw1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw1.DoWork
        While True ' <-- Thread will be killed automatically when app exits
            System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5).TotalMilliseconds)
 
            SyncLock PortLock ' <-- Thread will STOP & WAIT here if other thread currently has "PortLock"
                ' send request to Port 1
 
                ' wait for data to come back
 
                ' process data...but do NOT update GUI from in here!
 
                bgw1.ReportProgress(-1) ' causes ProgressChanged() Event below to fire
                ' (you can pass data using a second param if desired)
            End SyncLock
        End While
    End Sub
 
    Private Sub bgw1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw1.ProgressChanged
        ' it is SAFE to update the GUI from in here...
        ' (if you passed data access it with "e.UserState")
        Debug.Print("Port 1 Progress @ " & DateTime.Now)
    End Sub
 
    Private Sub bgw2_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw2.DoWork
        While True ' <-- Thread will be killed automatically when app exits
            System.Threading.Thread.Sleep(TimeSpan.FromSeconds(30).TotalMilliseconds)
 
            SyncLock PortLock ' <-- Thread will STOP & WAIT here if other thread currently has "PortLock"
                ' send request to Port 2
 
                ' wait for data to come back
 
                ' process data...but do NOT update GUI from in here!
 
                bgw2.ReportProgress(-1) ' causes ProgressChanged() Event below to fire
                ' (you can pass data using a second param if desired)
            End SyncLock
        End While
    End Sub
 
    Private Sub bgw2_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw2.ProgressChanged
        ' it is SAFE to update the GUI from in here...
        ' (if you passed data access it with "e.UserState")
        Debug.Print("Port 2 Progress @ " & DateTime.Now)
    End Sub
 
End Class

Open in new window

DualBackgroundWorkerOutput.jpg
0
 

Author Comment

by:vj_mi
ID: 24830291
Hello Idle_Mind,
I want:
5 secs --> Serial Port 1 (Timer 1)
Next 30 secs --> Serial Port 1 (Timer 2)

Again 5 secs --> Serial Port 1 (using Timer 1)
Next 30 secs -- Serial Port 1 (using Timer 2)

So both data is coming from single serial port. So in this case both timer should work independently. This means that first timer can have any interval and must not be dependent and must also not interfere with timer interval of timer 2. Now I cannot remove the timer control because that will affect my complete project which is almost ready. So I appreciate this backgroundworker concept but it may not be feasible to implement at this stage.  Based on your indication that we can use two timer controls on one form, let me try a sample and I will revert back.

Regards,
MI
0
 

Author Comment

by:vj_mi
ID: 24830370
One more point:
My current code is as follows:

Dim sp as new SerialPort.

1. With this declaration, can I still use two timer controls?

2. What happens if code in timer 1 does not get completed and meantime timer2 event gets fired?

Regards,
MI
0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24830889
Your Timer diagram and your description contradict each other:

    "...both timer should work independently. This means that first timer can have any interval and must not be dependent and must also not interfere with timer interval of timer 2."

With that statement you would actually have:

    5 secs Timer1 (@5 secs)
    5 secs Timer1 (@10 secs)
    5 secs Timer1 (@15 secs)
    5 secs Timer1 (@20 secs)
    5 secs Timer1 (@25 secs)
    5 secs Timer1 (@30 secs)
  30 secs Timer2 (@30 secs)
    5 secs Timer1 (@35 secs)
    5 secs Timer1 (@40 secs)
    5 secs Timer1 (@45 secs)
    5 secs Timer1 (@50 secs)
    5 secs Timer1 (@55 secs)
    5 secs Timer1 (@60 secs)
  30 secs Timer2 (@60 secs)
    etc...
   
But your diagram is showing:

    5 secs Timer1 (@5 secs)
  30 secs Timer2 (@35 secs)
    5 secs Timer1 (@40 secs)
  30 secs Timer2 (@70 secs)
    5 secs Timer1 (@75 secs)
  30 secs Timer2 (@105 secs)

If you really want the SECOND scenario then just do this:
Public Class Form1
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Timer1.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds
        Timer2.Interval = TimeSpan.FromSeconds(30).TotalMilliseconds
 
        Timer1.Enabled = True
        Timer2.Enabled = False
    End Sub
 
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Timer1.Stop()
 
        ' ... code ...
 
        Timer2.Start()
    End Sub
 
    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        Timer2.Stop()
 
        ' ... code ...
 
        Timer1.Start()
    End Sub
 
End Class

Open in new window

0
 

Author Comment

by:vj_mi
ID: 24835107
Sorry ... I think I did not put it correctly, but you understood it well.... I want:
   5 secs Timer1 (@5 secs)
    5 secs Timer1 (@10 secs)
    5 secs Timer1 (@15 secs)
    5 secs Timer1 (@20 secs)
    5 secs Timer1 (@25 secs)
    5 secs Timer1 (@30 secs)
  30 secs Timer2 (@30 secs)
    5 secs Timer1 (@35 secs)
    5 secs Timer1 (@40 secs)
    5 secs Timer1 (@45 secs)
    5 secs Timer1 (@50 secs)
    5 secs Timer1 (@55 secs)
    5 secs Timer1 (@60 secs)
  30 secs Timer2 (@60 secs)
    etc...

This is what I want to have. How to achieve this? Also note that at 30 secs, both timer 1  and timer 2 would be triggered. Will this create any problem since it has to execute two different set of codes for two different timers?

Regards,
MI
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24835164
It really depends on the type of code that is executing in the Tick() events of your Timers.

The Timer control runs in the SAME thread as the form.  So if you have synchronous, non-threaded code AND you are NOT calling Application.DoEvents() inside the Tick() events, then the first Tick() event to fire and be processed will execute and run to completion without interruption.  When it is done, then the second Tick() event will be processed (including any other messages pending in the message queue).
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24835166
*Oh...to achieve this you would simply set the Interval and Enable both Timers...
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question