|
-
Feb 9th, 2010, 10:45 AM
#1
Thread Starter
Lively Member
[RESOLVED] complicated timer loop
i have the following code to ping a list of switches , basically i want to add a timer to run at the end once the pings are finished and when the timer reaches a pre-determined value (long frequency) i want the ping process to start again , i want this process to keep repeating until btnoff is pressed. im having trouble because the code uses multithreading and ui threads whcih im not too familiar with.
ive tried adding in the timer below which ive commented out because it was giving an error when the pings were completed.
any ideas ?
**code is posted below
Last edited by markhorgan1; Feb 9th, 2010 at 10:47 AM.
Reason: over 10,000 characters
-
Feb 9th, 2010, 10:46 AM
#2
Thread Starter
Lively Member
Re: complicated timer loop
Code:
Imports System.Data
Imports System.Data.OleDb
Public Class Form5
Dim frequency As Long
Private Sub btnON_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnON.Click
If ComboBox1.Text = "" Then ' ensures combo box is not left blank
MsgBox("Please select scan frequency", [vbOKOnly]) ' prompts user to enter scan frequency
'sets scan frequency
Else
btnBack.Enabled = False
ComboBox1.Enabled = False
lblMin.Enabled = False
lblFrequency.Enabled = False
btnOff.Enabled = True
btnON.Enabled = False
lblOff.Visible = False
PictureBox1.Visible = False
lblOn.Visible = True
PictureBox2.Visible = True 'enables/hides the relevant picture boxs, labels and buttons based on user selection
RichTextBox1.Visible = True
Counter = 0 'reset the counter in case this is not the first time the ping button has been clicked
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
End If
If ComboBox1.Text = "15" Then
frequency = 900000
ElseIf ComboBox1.Text = "20" Then ' 60000ms in minute
frequency = 1200000
ElseIf ComboBox1.Text = "30" Then
frequency = 1800000
ElseIf ComboBox1.Text = "60" Then
frequency = 3600000000
End If
End Sub
Private Sub btnOff_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOff.Click
btnBack.Enabled = True
ComboBox1.Enabled = True
lblMin.Enabled = True
lblFrequency.Enabled = True
btnON.Enabled = True
btnOff.Enabled = False
lblOn.Visible = False
PictureBox2.Visible = False
lblOff.Visible = True
PictureBox1.Visible = True 'enables/hides the relevant picture boxs, labels and buttons based on user selection
End Sub
Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
Me.Hide() 'hides current form
Form3.Show() 'displays selected form
End Sub
''' <summary>
''' Represents a network switch (or any device with an IP) that is in the database
''' </summary>
Private Class NetworkSwitch
Private _IPAddress As String
Private _SwitchID As Integer
Private _SwitchName As String
Private _Result As Boolean
Private _ResponseTime As Integer
Public Property IPAddress() As String
Get
Return _IPAddress
End Get
Set(ByVal value As String)
_IPAddress = value
End Set
End Property
Public Property ResponseTime() As Integer
Get
Return _ResponseTime
End Get
Set(ByVal value As Integer)
_ResponseTime = value
End Set
End Property
Public Property SwitchName() As String
Get
Return _SwitchName
End Get
Set(ByVal value As String)
_SwitchName = value
End Set
End Property
Public Property SwitchID() As Integer
Get
Return _SwitchID
End Get
Set(ByVal value As Integer)
_SwitchID = value
End Set
End Property
Public Property Result() As Boolean
Get
Return _Result
End Get
Set(ByVal value As Boolean)
_Result = value
End Set
End Property
End Class
'Set up some variables that we will use from various functions/subs
Private PingList As List(Of NetworkSwitch)
Private Counter As Integer = 0
Private ConnString As New OleDbConnectionStringBuilder("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=H:\FYP-trial\NetworkMap\Network Map.mdb;User Id=admin;Password=;")
'This is the Delegate that will be used to pass data between the threads safely
Private Delegate Sub PingComplete(ByVal sw As NetworkSwitch)
Private Sub BG_CollectData()
'Create our connection that will be used to connect to the Access database
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
'Create the command that will be used to select all of the data in the IP and ID columns
Dim SelectCommand As New OleDbCommand("SELECT * FROM tblSwitch ", AccessConnection)
'Create a new instance of a list of our NetworkSwitch class
PingList = New List(Of NetworkSwitch)
'Open the connection to the database
AccessConnection.Open()
'Use a DataReader to access the data that the SELECT command returns
Dim Reader As OleDbDataReader = SelectCommand.ExecuteReader
'Start to loop through the results
'This loop will be restarted for each row in the database
Do While Reader.Read
'Create a new instance of our NetworkSwitch class and populate the ID and IP properties
'with data from the current row in the database that we are looping through
Dim CurrentSwitch As New NetworkSwitch
With CurrentSwitch
.SwitchID = Reader("SwitchID")
.SwitchName = Reader("SwitchName")
.IPAddress = Reader("IPAddress")
End With
'Add the new instance of the NetworkSwitch to our list
PingList.Add(CurrentSwitch)
Loop 'Start the loop again for the next record in the database
'Close the connection because we have now processed all rows in the database
AccessConnection.Close()
'Give the threadpool a limit so that no more than 30 threads are running at the same time
Threading.ThreadPool.SetMaxThreads(30, 400)
'Loop through our list of NetworkSwitch instances and start (well, queue up) a new background
'thread for each item in the list and passes it the current item in the loop (which is a NetworkSwitch object)
For Each switchobject As NetworkSwitch In PingList
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf DoPing), switchobject)
Next
End Sub
''' <summary>
''' Performs the ping and updates the Result property of the NetworkSwitch object that was passed to this
''' </summary>
Private Sub DoPing(ByVal Switch As NetworkSwitch)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Dim ResponseTime As Integer
Result = SendPing.Send(Switch.IPAddress)
ResponseTime = Result.RoundtripTime
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
Switch.ResponseTime = ResponseTime
Else
Switch.Result = False
End If
UpdateDatabase(Switch)
Counter += 1
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
End Sub
''' <summary>
''' This is executed each time a ping completes and the database has been updated.
''' It is executed on the UI thread because we used Me.Invoke to call it so it can access
''' controls on the UI thread without a problem
''' </summary>
Private Sub UI_PingComplete(ByVal sw As NetworkSwitch)
If sw.Result = True Then
RichTextBox1.SelectionColor = Color.DarkBlue
ElseIf sw.Result = False Then
RichTextBox1.SelectionColor = Color.Red
End If
RichTextBox1.AppendText(sw.SwitchID & "--" & sw.SwitchName & " -- " & sw.IPAddress & " -- Reply -> " & sw.Result & "--ResponseTime--" & sw.ResponseTime & "ms" & vbNewLine) 'update our log textbox
If Counter = PingList.Count Then
RichTextBox1.AppendText(vbNewLine & vbNewLine & "Finished re-trying devices" & vbNewLine)
MsgBox("Finished re-trying devices", [vbOKOnly])
' Timer1 = Nothing
PingList = Nothing 'clean up
' Timer1.Enabled = True
' Timer1.Start()
' If Timer1.Equals(frequency) Then
'Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
' bgthread.IsBackground = True 'Make the thread end if the program is closed
'bgthread.Start() 'Start the background thread
' End If
End If
End Sub
Private Sub UpdateDatabase(ByVal sw As NetworkSwitch)
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim UpdateCommand As New OleDbCommand("UPDATE tblSwitch SET Result=@Result, LastTested=@CurrentTime, ResponseTime=@ResponseTime WHERE SwitchID=@SwitchID", AccessConnection)
With UpdateCommand.Parameters
.Add("@Result", OleDbType.Boolean).Value = sw.Result
.Add("@CurrentTime", OleDbType.Char).Value = Now.ToString
.Add("@ResponseTime", OleDbType.Integer).Value = sw.ResponseTime
.Add("@SwitchID", OleDbType.Integer).Value = sw.SwitchID
End With
AccessConnection.Open() 'dont delete
UpdateCommand.ExecuteNonQuery() 'Execute the command that updates the database
AccessConnection.Close() 'dont delete
End Sub
End Class
-
Feb 9th, 2010, 12:37 PM
#3
Fanatic Member
Re: complicated timer loop
Ah i see it:- this is the code you have wrong
Code:
MsgBox("Finished re-trying devices", [vbOKOnly])
' Timer1 = Nothing
PingList = Nothing 'clean up
' Timer1.Enabled = True
' Timer1.Start()
' If Timer1.Equals(frequency) Then
'Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
' bgthread.IsBackground = True 'Make the thread end if the program is closed
'bgthread.Start() 'Start the background thread
' End If
the first part is right so keep this
Code:
MsgBox("Finished re-trying devices", [vbOKOnly])
Timer1 = Nothing
PingList = Nothing 'clean up
Timer1.Enabled = True
Timer1.Start()
go onto the Design page for the form ands double click the timer, this creates a timer Tick sub to deal with when the timer has ticked. within this block paste this
Code:
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
Timer1.Stop() 'Stop the timer till you need to do the count again
If debugging is the process of removing bugs, then programming must be the process of putting them in.
-
Feb 10th, 2010, 08:19 AM
#4
Thread Starter
Lively Member
Re: complicated timer loop
thanks megalith ive made those changes one last thing tho i cant seem to find how the timer knows when to tick ?
is it done by setting the interval on the timer or do i set a value that the timer compares itself to ? e.g. like i originally had below
Code:
If Timer1.Equals(frequency) Then ....
-
Feb 10th, 2010, 09:26 AM
#5
Fanatic Member
Re: complicated timer loop
yes you set the interval on the timer (which is in millseconds) you can do it either in design or while the code runs, with this example, unless you do plan to change the delay) i'd do it in design.
If debugging is the process of removing bugs, then programming must be the process of putting them in.
-
Feb 10th, 2010, 10:01 AM
#6
Thread Starter
Lively Member
Re: complicated timer loop
yeah i need to do it while the code runs because the interval is selected by the user before the loop runs for the first time. i tried setting the interval but I am now getting a nullreference error(object reference not set to an instance of an object) at this line after code runs for first time.
Code:
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
** ive posted the code with the timer changes below
Last edited by markhorgan1; Feb 10th, 2010 at 10:04 AM.
Reason: code posted below
-
Feb 10th, 2010, 10:04 AM
#7
Thread Starter
Lively Member
Re: complicated timer loop
Code:
Imports System.Data
Imports System.Data.OleDb
Public Class Form5
Dim frequency As Long
Private Sub btnON_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnON.Click
If ComboBox1.Text = "" Then ' ensures combo box is not left blank
MsgBox("Please select scan frequency", [vbOKOnly]) ' prompts user to enter scan frequency
'sets scan frequency
Else
btnBack.Enabled = False
ComboBox1.Enabled = False
lblMin.Enabled = False
lblFrequency.Enabled = False
btnOff.Enabled = True
btnON.Enabled = False
lblOff.Visible = False
PictureBox1.Visible = False
lblOn.Visible = True
PictureBox2.Visible = True 'enables/hides the relevant picture boxs, labels and buttons based on user selection
RichTextBox1.Visible = True
Counter = 0 'reset the counter in case this is not the first time the ping button has been clicked
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
End If
If ComboBox1.Text = "15" Then
frequency = 600000 ' should be 90 but 60 for demo sake
'frequency = Timer1.Interval
ElseIf ComboBox1.Text = "20" Then ' 60000ms in minute
frequency = 1200000
ElseIf ComboBox1.Text = "30" Then
frequency = 1800000
ElseIf ComboBox1.Text = "60" Then
frequency = 3600000000
End If
End Sub
Private Sub btnOff_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOff.Click
btnBack.Enabled = True
ComboBox1.Enabled = True
lblMin.Enabled = True
lblFrequency.Enabled = True
btnON.Enabled = True
btnOff.Enabled = False
lblOn.Visible = False
PictureBox2.Visible = False
lblOff.Visible = True
PictureBox1.Visible = True 'enables/hides the relevant picture boxs, labels and buttons based on user selection
End Sub
Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
Me.Hide() 'hides current form
Form3.Show() 'displays selected form
End Sub
Private Class NetworkSwitch
Private _IPAddress As String
Private _SwitchID As Integer
Private _SwitchName As String
Private _Result As Boolean
Private _ResponseTime As Integer
Public Property IPAddress() As String
Get
Return _IPAddress
End Get
Set(ByVal value As String)
_IPAddress = value
End Set
End Property
Public Property ResponseTime() As Integer
Get
Return _ResponseTime
End Get
Set(ByVal value As Integer)
_ResponseTime = value
End Set
End Property
Public Property SwitchName() As String
Get
Return _SwitchName
End Get
Set(ByVal value As String)
_SwitchName = value
End Set
End Property
Public Property SwitchID() As Integer
Get
Return _SwitchID
End Get
Set(ByVal value As Integer)
_SwitchID = value
End Set
End Property
Public Property Result() As Boolean
Get
Return _Result
End Get
Set(ByVal value As Boolean)
_Result = value
End Set
End Property
End Class
Private PingList As List(Of NetworkSwitch)
Private Counter As Integer = 0
Private ConnString As New OleDbConnectionStringBuilder("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=H:\FYP-trial\NetworkMap\Network Map.mdb;User Id=admin;Password=;")
'This is the Delegate that will be used to pass data between the threads safely
Private Delegate Sub PingComplete(ByVal sw As NetworkSwitch)
Private Sub BG_CollectData()
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim SelectCommand As New OleDbCommand("SELECT * FROM tblSwitch ", AccessConnection)
'Create a new instance of a list of our NetworkSwitch class
PingList = New List(Of NetworkSwitch)
AccessConnection.Open()
'Use a DataReader to access the data that the SELECT command returns
Dim Reader As OleDbDataReader = SelectCommand.ExecuteReader
'Start to loop through the results
'This loop will be restarted for each row in the database
Do While Reader.Read
'Create a new instance of our NetworkSwitch class and populate the ID and IP properties
'with data from the current row in the database that we are looping through
Dim CurrentSwitch As New NetworkSwitch
With CurrentSwitch
.SwitchID = Reader("SwitchID")
.SwitchName = Reader("SwitchName")
.IPAddress = Reader("IPAddress")
End With
'Add the new instance of the NetworkSwitch to our list
PingList.Add(CurrentSwitch)
Loop 'Start the loop again for the next record in the database
'Close the connection because we have now processed all rows in the database
AccessConnection.Close()
'Give the threadpool a limit so that no more than 30 threads are running at the same time
Threading.ThreadPool.SetMaxThreads(30, 400)
'Loop through our list of NetworkSwitch instances and start (well, queue up) a new background
'thread for each item in the list and passes it the current item in the loop (which is a NetworkSwitch object)
For Each switchobject As NetworkSwitch In PingList
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf DoPing), switchobject)
Next
End Sub
Private Sub DoPing(ByVal Switch As NetworkSwitch)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Dim ResponseTime As Integer
Result = SendPing.Send(Switch.IPAddress)
ResponseTime = Result.RoundtripTime
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
Switch.ResponseTime = ResponseTime
Else
Switch.Result = False
End If
UpdateDatabase(Switch)
Counter += 1
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
End Sub
Private Sub UI_PingComplete(ByVal sw As NetworkSwitch)
If sw.Result = True Then
RichTextBox1.SelectionColor = Color.DarkBlue
ElseIf sw.Result = False Then
RichTextBox1.SelectionColor = Color.Red
End If
RichTextBox1.AppendText(sw.SwitchID & "--" & sw.SwitchName & " -- " & sw.IPAddress & " -- Reply -> " & sw.Result & "--ResponseTime--" & sw.ResponseTime & "ms" & vbNewLine) 'update our log textbox
If Counter = PingList.Count Then
RichTextBox1.AppendText(vbNewLine & vbNewLine & "Finished re-trying devices" & vbNewLine)
MsgBox("Finished re-trying devices", [vbOKOnly])
Timer1 = Nothing
PingList = Nothing 'clean up
Timer1.Enabled = True
frequency = Timer1.Interval
Timer1.Start()
' If Timer1.Equals(frequency) Then
'Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
' bgthread.IsBackground = True 'Make the thread end if the program is closed
'bgthread.Start() 'Start the background thread
' End If
End If
End Sub
Private Sub UpdateDatabase(ByVal sw As NetworkSwitch)
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim UpdateCommand As New OleDbCommand("UPDATE tblSwitch SET Result=@Result, LastTested=@CurrentTime, ResponseTime=@ResponseTime WHERE SwitchID=@SwitchID", AccessConnection)
With UpdateCommand.Parameters
.Add("@Result", OleDbType.Boolean).Value = sw.Result
.Add("@CurrentTime", OleDbType.Char).Value = Now.ToString
.Add("@ResponseTime", OleDbType.Integer).Value = sw.ResponseTime
.Add("@SwitchID", OleDbType.Integer).Value = sw.SwitchID
End With
AccessConnection.Open() 'dont delete
UpdateCommand.ExecuteNonQuery() 'Execute the command that updates the database
AccessConnection.Close() 'dont delete
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
Timer1.Stop() 'Stop the timer till you need to do the count again
End Sub
End Class
-
Feb 11th, 2010, 05:31 AM
#8
Thread Starter
Lively Member
Re: complicated timer loop
i have the timer working now,few things were in the wrong place, but it only works when i set the interval in design view is there a way to set it equal to a long which the user specifies ? before / after the timer is enabled
-
Feb 11th, 2010, 08:06 AM
#9
Fanatic Member
Re: complicated timer loop
yes you simply use
Code:
Timer1.Interval = someTimeInMilliseconds
glad you have it working though
If debugging is the process of removing bugs, then programming must be the process of putting them in.
-
Feb 11th, 2010, 08:16 AM
#10
Thread Starter
Lively Member
Re: [RESOLVED] complicated timer loop
perfect , problem wasnt what i had but was where i was putting it
thanks megalith
-
Feb 11th, 2010, 08:20 AM
#11
Fanatic Member
Re: [RESOLVED] complicated timer loop
no probs, glad i could help
If debugging is the process of removing bugs, then programming must be the process of putting them in.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|