Updating progress bar from threadpool - vb.net

Im trying to update a progress bar in my main form from a threadpool but everything Iv'e tried so far updates the value of the progress bar but not the physical appearance of it, Tried several different ways and still can't find a solution. Can someone please point me in the right direction to update the progress bar on my form1 by 1 every time a thread has completed.
Imports System.Threading
Public Class Form1
Dim arry As New List(Of String)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
BackgroundWorker1.RunWorkerAsync()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim ii As Integer = 2000
For a As Integer = 0 To ii
arry.Add(a)
Next
ProgressBar1.Maximum = arry.Count
ThreadPool.SetMaxThreads(4, 4)
Dim doneEvents(arry.Count) As ManualResetEvent
Dim r As New Random()
For i As Integer = 0 To arry.Count
doneEvents(i) = New ManualResetEvent(False)
Dim f = New stuff(r.Next(20, 40), doneEvents(i))
ThreadPool.QueueUserWorkItem(AddressOf f.ThreadPoolCallBack, i)
Next
For Each handle As WaitHandle In doneEvents
handle.WaitOne()
Next
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CheckForIllegalCrossThreadCalls = False
End Sub
Private Delegate Sub FillDelegate()
Public Sub Fill()
If ProgressBar1.InvokeRequired Then
ProgressBar1.BeginInvoke(New FillDelegate(AddressOf Fill))
Else
ProgressBar1.Increment(1)
ProgressBar1.Refresh()
End If
End Sub
End Class
Public Class stuff
Private _doneEvent As ManualResetEvent
Private _n As Integer
Public ReadOnly Property N() As Integer
Get
Return _n
End Get
End Property
Sub New(ByVal n As Integer, ByVal doneEvent As ManualResetEvent)
_n = n
_doneEvent = doneEvent
End Sub
Public Sub ThreadPoolCallBack(ByVal threadContext As Object)
Try
Dim threadIndex As Integer = CType(threadContext, Integer)
Console.WriteLine("thread {0} started...", threadIndex)
Form1.Fill()
Console.WriteLine("thread {0} finished...", threadIndex)
Catch ex As Exception
Console.WriteLine("error in threadPoolCallback")
Console.WriteLine(ex.Message)
Finally
_doneEvent.Set()
End Try
End Sub
End Class

Related

vb.net System.ArgumentOutOfRangeException When Trying to ping

been trying to follow this guide on how to make picture boxes change colour depending on if the ping has been successful or not. I have some test ip's in a CSV file that the program imports
but I keep getting a exception error. I have 3 picture boxes on the page currently defined from picturebox2 - 4
the code for the whole page is below, any suggestions or fixes would be greatly appreciated
Imports System.Net
Imports System.Net.NetworkInformation
Imports System.Threading
Imports System.IO
Imports System.Timers
Public Class Central
Dim pingTable As DataTable = New DataTable()
Dim ipAddress As List(Of String) = New List(Of String)
Dim pictureBoxList As List(Of PictureBox) = New List(Of PictureBox)
Dim timer As Timers.Timer
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
timer = New Timers.Timer
timer.Interval = 20000
timer.Enabled = True
AddHandler timer.Elapsed, AddressOf OnElapsedTime
End Sub
Private Sub OnElapsedTime(ByVal sender As Object, ByVal e As ElapsedEventArgs)
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub FillPingTable()
pingTable.Columns.Add("ip", GetType(String))
pingTable.Columns.Add("picturebox", GetType(String))
pingTable.Rows.Add()
For i As Integer = 0 To ipAddress.Count - 1
pingTable.Rows.Add(ipAddress(i), pictureBoxList(i))
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Hide()
Scot.Show()
End Sub
Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click
Hide()
Home.Show()
End Sub
Private Sub central_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Using reader = New StreamReader("A:\IpAddress.csv")
While Not reader.EndOfStream
Dim line = reader.ReadLine
Dim values = line.Split(ChrW(10))
ipAddress.Add(values(0))
End While
For i As Integer = 1 To 2
pictureBoxList.Add(CType(Controls.Find("PictureBox" & i, True)(0), PictureBox))
FillPingTable()
BackgroundWorker1.RunWorkerAsync()
Next
End Using
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Thread.Sleep(500)
Parallel.For(0, ipAddress.Count(), Sub(i, loopState)
Dim ping As New Ping()
Dim pingReply As PingReply = ping.Send(ipAddress(i).ToString())
Me.BeginInvoke(CType(Sub()
pictureBoxList(i).SizeMode = PictureBoxSizeMode.Zoom
pictureBoxList(i).BackColor = If(pingReply.Status = IPStatus.Success, Color.Green, Color.Red)
End Sub, Action))
End Sub)
End Sub
End Class

How can I cancel a thread?

I do something in a thread. But sometimes I don't want to wait till all pings are finished.
How can I cancel a thread?
Can you show me please the code?
Private Sub Start_Button_Click(sender As Object, e As EventArgs) Handles Start_Button.Click
DoSomething()
End Sub
Private Sub Cancel_Button_Click(sender As Object, e As EventArgs) Handles Cancel_Button.Click
THRD.Cancel '<-- Thread cancel!??!???
End Sub
Sub DoSomething()
Dim THRD As New Thread(Sub()
Dim IPArea As String = "192.168.1."
Dim LastIP As Integer
For LastIP = 0 To 255
Dim TestIP As String = IPArea & CStr(LastIP)
If My.Computer.Network.Ping(TestIP, 10) Then
ListBox1.Items.Add(TestIP)
End If
Next
End Sub)
THRD.IsBackground = True
THRD.Start()
End Sub
Here is my working solution and this solution is only to show how to move the THRD as a form level variable to allow stopping it when clicking the cancel button. I added some validations to prevent exceptions.
Public Class Form1
Private THRD As Threading.Thread
Private Sub Start_Button_Click(sender As Object, e As EventArgs) Handles Start_Button.Click
DoSomething()
End Sub
Private Sub Cancel_Button_Click(sender As Object, e As EventArgs) Handles Cancel_Button.Click
If THRD IsNot Nothing AndAlso THRD.IsAlive Then
THRD.Abort() '<-- Thread cancel!??!???
THRD = Nothing
AddToList("Stopped.")
Else
AddToList("Thread not running.")
End If
End Sub
Sub DoSomething()
If THRD IsNot Nothing AndAlso THRD.IsAlive Then
AddToList("Still working...")
Exit Sub
End If
THRD = New Threading.Thread(Sub()
Dim IPArea As String = "192.168.1."
Dim LastIP As Integer
For LastIP = 0 To 255
Dim TestIP As String = IPArea & CStr(LastIP)
If My.Computer.Network.Ping(TestIP, 10) Then
AddToList(TestIP)
End If
Next
AddToList("Done")
End Sub)
THRD.IsBackground = True
THRD.Start()
End Sub
''' <summary>
''' Thead-safe add value to list.
''' </summary>
''' <param name="value">The value.</param>
Private Sub AddToList(value As String)
If ListBox1.InvokeRequired Then
ListBox1.Invoke(Sub() ListBox1.Items.Add(value))
Else
ListBox1.Items.Add(value)
End If
End Sub
End Class

Random delay in seconds from numericupdown in VB.Net

I have a desktop winforms app code:
Sub Delay(ByVal dblSecs As Double)
Const OneSec As Double = 1.0# / (1440.0# * 60.0#)
Dim dblWaitTil As Date
Now.AddSeconds(OneSec)
dblWaitTil = Now.AddSeconds(OneSec).AddSeconds(dblSecs)
Do Until Now > dblWaitTil
Application.DoEvents()
Loop
End Sub
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
Webbrowser1.Navigate(TextBox1.Text)
Delay(Val(DelayText.Text))
end sub
What I need is to set max. delay, same from textbox by entering seconds.
I need this to be random delay number so Im stacking here, thanks for correcting my code.
Also If its possible to make it in NumericUpDown, as i found some topics which says textbox text property is different as NumericUpDown but i like it more.
You could use an inbetween class which does most of the work for you
This class would take the WebBrowser, attach to some events of it, and would refresh periodically (depending on MinimumWait / MaximumWait)
As it is using threading, it also checks if the usercontrol needs to be invoked to Refresh it and when yes, invokes the custom refresh delegate
Public Class Refresher
Protected Delegate Sub RefreshNavigationDelegate(browser As WebBrowser)
Protected Sub RefreshNavigation(browser As WebBrowser)
If browser.InvokeRequired Then
browser.Invoke(New RefreshNavigationDelegate(AddressOf RefreshNavigation), browser)
Return
End If
browser.Refresh(WebBrowserRefreshOption.Completely)
End Sub
Private _isBusy As Boolean = False
Public Property IsBusy As Boolean
Get
Return _isBusy
End Get
Protected Set(value As Boolean)
If _isBusy = value Then
Return
End If
_isBusy = value
End Set
End Property
Public Property MinimumWait As Integer = 2000
Public Property MaximumWait As Integer = 10000
Private refreshThread As Thread = Nothing
Private _browser As WebBrowser
Public Property Browser As WebBrowser
Get
Return _browser
End Get
Set(value As WebBrowser)
If Object.Equals(_browser, value) Then
Return
End If
StopRefresh()
If _browser IsNot Nothing Then
RemoveHandler Browser.DocumentCompleted, AddressOf DocumentComplete
RemoveHandler Browser.Navigating, AddressOf Navigating
End If
_browser = value
If _browser IsNot Nothing Then
AddHandler Browser.DocumentCompleted, AddressOf DocumentComplete
AddHandler Browser.Navigating, AddressOf Navigating
AddHandler Browser.ProgressChanged, AddressOf ProgressChanged
End If
StartRefresh()
End Set
End Property
Protected Sub ProgressChanged(sender As Object, e As WebBrowserProgressChangedEventArgs)
IsBusy = e.CurrentProgress > 0 AndAlso e.CurrentProgress < e.MaximumProgress
End Sub
Protected Sub DocumentComplete(sender As Object, e As WebBrowserDocumentCompletedEventArgs)
IsBusy = False
End Sub
Protected Sub Navigating(sender As Object, e As WebBrowserNavigatingEventArgs)
IsBusy = True
End Sub
Public Sub StartRefresh()
If refreshThread IsNot Nothing Then
Return
End If
refreshThread = New Thread(AddressOf DoRandomRefreshes)
refreshThread.Start()
End Sub
Public Sub StopRefresh()
If refreshThread Is Nothing Then
Return
End If
refreshThread.Abort()
refreshThread = Nothing
End Sub
Protected Overridable Sub DoRandomRefreshes()
Dim randomGenerator As New Random()
While Not refreshThread.ThreadState = ThreadState.AbortRequested
Dim newTimeout As Integer = MinimumWait + randomGenerator.Next(MaximumWait - MinimumWait)
Thread.Sleep(newTimeout)
If Not IsBusy Then
RefreshNavigation(Browser)
End If
End While
End Sub
Public Sub New()
End Sub
End Class
You could then use it in your form as such:
Public Class Form1
Dim myRefresher As Refresher = New Refresher()
Private Sub tsbGo_Click(sender As Object, e As EventArgs) Handles tsbGo.Click
WebBrowser1.Navigate(txtUrl.Text)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
myRefresher.Browser = WebBrowser1
End Sub
Private Sub txtMin_TextChanged(sender As Object, e As EventArgs) Handles txtMin.TextChanged
Dim int As Integer = 0
If Integer.TryParse(txtMin.Text, int) Then
myRefresher.MinimumWait = int
End If
End Sub
Private Sub txtMax_TextChanged(sender As Object, e As EventArgs) Handles txtMax.TextChanged
Dim int As Integer = 0
If Integer.TryParse(txtMax.Text, int) Then
myRefresher.MaximumWait = int
End If
End Sub
End Class

vb2012 textbox backcolor does't change using thread

I wrote very simple thread example.
Make normal form1 and drop 1 textbox
run thread work on form load
thread change a textbox backcolor looks like switch on/off
But, it doesn't work.....
Can you tell me why doesn't work??
see my source.
=====================================================================
Imports System.Threading
Public Class Monitor
Public wObj As Worker = New Worker()
Public MyThread As Thread = New Thread(AddressOf wObj.DoWork)
Public Sub ChangeTBColor(pOption As Integer)
If pOption = 1 Then
tb1.BackColor = Color.Aqua
Else
tb1.BackColor = Color.Red
End If
End Sub
Private Sub Monitor_Load(sender As Object, e As EventArgs) Handles Me.Load
MyThread.Start()
Console.WriteLine("Running OrgThread..")
Console.WriteLine("Stop running")
End Sub
Private Sub BtnThreadStop_Click(sender As Object, e As EventArgs) Handles BtnThreadStop.Click
Me.wObj.RequestStop()
End Sub
End Class
Public Class Worker
Private LoopStop As Boolean = True
Public Sub DoWork()
Console.WriteLine("User Thread Start!")
Dim iTemp As Integer = 0
While (LoopStop)
Monitor.ChangeTBColor(iTemp Mod 2)
iTemp = iTemp + 1
Thread.Sleep(500)
End While
Console.WriteLine("User Thread End.!")
End Sub
Public Sub RequestStop()
LoopStop = False
End Sub
End Class
As already mentioned, your starting a new thread for your work, the issue is your trying to change the color for a control that need invoking. With this said, we need a delegate for when the control needs to be invoked... In my example, I used one class that handles this all and works great. Also please make sure to import System.ComponentModel because this is needed for the BackgroundWorker... I used the background worker as it takes all the heavy lifting off you would need...
Imports System.ComponentModel
Imports System.Threading
Public Class Monitor
Delegate Sub SetColor(ByVal clr As Integer) 'Your delegate..
Private WithEvents bw As New BackgroundWorker
Public Sub ChangeTBColor(pOption As Integer)
If Me.tb1.InvokeRequired Then 'Invoke if required...
Dim d As New SetColor(AddressOf ChangeTBColor) 'Your delegate...
Me.Invoke(d, New Object() {pOption})
Else
If pOption = 1 Then
tb1.BackColor = Color.Aqua
Else
tb1.BackColor = Color.Red
End If
End If
End Sub
Private Sub Monitor_Load(sender As Object, e As EventArgs) Handles Me.Load
bw.WorkerSupportsCancellation = True
Console.WriteLine("Running OrgThread..")
bw.RunWorkerAsync()
End Sub
Private Sub bw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
Dim iTemp As Integer = 0
Dim LoopStop As Boolean = True
Console.WriteLine("User Thread Start!")
While (LoopStop)
If Not (bw.CancellationPending) Then
ChangeTBColor(iTemp Mod 2)
iTemp = iTemp + 1
Thread.Sleep(500)
Else
e.Cancel = True
LoopStop = False
End If
End While
End Sub
Private Sub bw_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
Console.WriteLine("User Thread End.!")
End Sub
Private Sub BtnThreadStop_Click(sender As Object, e As EventArgs) Handles BtnThreadStop.Click
If bw.IsBusy Then
bw.CancelAsync()
Else
Console.WriteLine("Running OrgThread..")
bw.RunWorkerAsync()
End If
End Sub
End Class
Here's my screenshot of my test... This is tried and tested. Please be sure to vote if this helps you!

How to run a thread every x seconds without using timer control

I have to run a certain thread every second refreshes the message field, but without using any time controls. I wonder if there is any alternative to timer control. My be background worker or something of that sort.
This what I have so far. It suppose to run every second but it doesn't
Private Sub main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim myThread As New System.Threading.Thread(AddressOf GetData)
myThread.Start()
Thread.Sleep(1000)
End Sub
And this is function which he is calling to:
Delegate Sub SetTextCallback(ByVal newString As String)
Private Sub SetText(ByVal [text] As String)
If Me.ChatBox.InvokeRequired Then
Dim d As New SetTextCallback(AddressOf SetText)
Me.Invoke(d, New Object() {[text]})
Else
Me.ChatBox.Text = [text]
End If
End Sub​
Sub GetData()
Try
conn.Open()
Dim Query = "SELECT * fROM messages where Time_Posted > Now()"
Dim cmd As MySqlCommand = New MySqlCommand(Query, conn)
Dim theREader As MySqlDataReader = cmd.ExecuteReader
SetText("")
Dim Temp as String = ""
Do While theREader.Read()
Temp &= theREader.GetString(0) & vbCrLf
Loop
SetText(Temp)
conn.Close()
Catch ex As Exception
MsgBox(ex.Message.ToString())
conn.Close()
End Try
GetData()
End Sub
I wonder if there any way how can I make the thread run repeatedly without using timer?
Thank you in advance for any help and suggestions
THIS IS CORRECTED CODE AFTER THE PROBLEM WAS SOLVED
look at this one then
Imports System.Threading
Public Class Form1
Dim testvalue As Integer
Private Sub main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim myThread As New System.Threading.Thread(AddressOf GetData)
myThread.Start()
Thread.Sleep(1000)
End Sub
Sub GetData()
MsgBox("getdata works")
'get your new data from database here
'threadsleep here if you want
'and call GetData() again
GetData()
End Sub
'
'
'
End Class
now i gotta make non stop proc read without any timer.You can add thread sleep if you want
paste it to new project
Public Class Form1
Dim testvalue As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
testvalue = 1
'now we gotta run our proc first time
Read(testvalue)
End Sub
Private Sub Read(ByVal msg As String)
MsgBox(msg)
testvalue += 1 'you make make threadsleep here if you want
Read(testvalue) 'after first start we did what we ant , and now we are running it again
End Sub
End Class