When I start a thread, the ThreadState always is "Unstarted" even if I do a "Thread.Abort()", my thread starts and finish the work good... I don't know why I get that always the same state.
Dim thread_1 As System.Threading.Thread = New Threading.Thread(AddressOf mithread)
thread_1.Start()
System.Threading.Thread.Sleep(100)
While not thread_1.ThreadState = Threading.ThreadState.Running
MsgBox(thread_1.ThreadState.ToString) ' "Unstarted"
thread_1.Abort()
MsgBox(thread_1.ThreadState.ToString) ' "Unstarted" again and again...
End While
UPDATE
This is the sub who calls the thread, and the problem is the "while" statament is not waiting,
PS: You can see a comment explanation at the middle of this sub:
public sub...
...
If Not playerargs = Nothing Then
If randomize.Checked = True Then
Dim thread_1 As System.Threading.Thread = New Threading.Thread(AddressOf mithread)
thread_1.Start()
System.Threading.Thread.Sleep(50)
While thread_1.ThreadState = Threading.ThreadState.Running
Windows.Forms.Application.DoEvents()
End While
Else
progresslabel.Text = "All files added..."
End If
' HERE IS THE PROBLEM, IF I CHECK "AUTOCLOSE" CHECKBOX THEN,
' THE FORM ALWAYS TRY TO CLOSE BEFORE THREAD IS COMPLETED:
' -----------------------------------------
If autoclose.Checked = True Then Me.Close()
'------------------------------------------
Else
...
End Sub
And here is the "mithread" thread:
Public Sub mithread()
Dim Str As String
Dim Pattern As String = ControlChars.Quote
Dim ArgsArray() As String
Str = Replace(playerargs, " " & ControlChars.Quote, "")
ArgsArray = Split(Str, Pattern)
Using objWriter As New System.IO.StreamWriter(Temp_file, False, System.Text.Encoding.UTF8)
Dim n As Integer = 0
Dim count As Integer = 0
Dim foldercount As Integer = -1
For Each folder In ArgsArray
foldercount += 1
If foldercount > 1 Then
InvokeControl(ProgBarPlus1, Sub(x) x.Max = foldercount)
End If
Next
If foldercount = 1 Then
For Each folder In ArgsArray
If Not folder = Nothing Then
Dim di As New IO.DirectoryInfo(folder)
Dim files As IO.FileInfo() = di.GetFiles("*")
Dim file As IO.FileInfo
InvokeControl(ProgBarPlus1, Sub(x) x.Max = files.Count)
For Each file In files
n += 1
CheckPrimeNumber(n)
count += 1
If file.Extension.ToLower = ".lnk" Then
Dim ShotcutTarget As String = Shortcut.ResolveShortcut((file.FullName).ToString())
objWriter.Write(ShotcutTarget & vbCrLf)
Else
objWriter.Write(file.FullName & vbCrLf)
End If
Next
End If
Next
ElseIf foldercount > 1 Then
For Each folder In ArgsArray
If Not folder = Nothing Then
Dim di As New IO.DirectoryInfo(folder)
Dim files As IO.FileInfo() = di.GetFiles("*")
Dim file As IO.FileInfo
InvokeControl(ProgBarPlus1, Sub(x) x.Value += 1)
For Each file In files
If file.Extension.ToLower = ".lnk" Then
Dim ShotcutTarget As String = Shortcut.ResolveShortcut((file.FullName).ToString())
objWriter.Write(ShotcutTarget & vbCrLf)
Else
objWriter.Write(file.FullName & vbCrLf)
End If
Next
End If
Next
End If
End Using
If Not thread_1.ThreadState = Threading.ThreadState.AbortRequested Then
MsgBox(thread_1.ThreadState.ToString)
Randomize_a_file.RandomizeFile(Temp_file)
InvokeControl(ProgBarPlus1, Sub(x) x.Value = 0)
' Process.Start(userSelectedPlayerFilePath, ControlChars.Quote & Temp_file.ToString() & ControlChars.Quote)
InvokeControl(progresslabel, Sub(x) x.Text = "All files launched...")
End If
End Sub
Its not easy to work out what your problem is, but i can say for sure a While Loop and DoEvents is not the way forward at all.
Instead raise an event when the thread has done all its work, subscribe to the event, and when it is raise close the form (if autoclose = true):
Public Class Form1
Public Event threadCompleted()
Public Sub New()
InitializeComponent()
AddHandler threadCompleted, AddressOf Me.Thread_Completed
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t1 As New Threading.Thread(AddressOf mithread)
t1.Start()
End Sub
Public Sub mithread()
'simulate some work:
Threading.Thread.Sleep(3000)
'then raise the event when done
RaiseEvent threadCompleted()
End Sub
Public Delegate Sub Thread_CompletedDelegate()
Private Sub Thread_Completed()
If Me.InvokeRequired Then
Me.BeginInvoke(New Thread_CompletedDelegate(AddressOf Thread_Completed))
Else
If autoclose.Checked = True Then
Me.Close()
End If
End If
End Sub
End Class
Or use a background worker which does all this, plus handles reporting progress and cancelation all for you.
Sounds like something is happening in mithread that is preventing the thread from fully starting. I ran similar code with an empty sub for mithread and I get the expected threadstate (Stopped then Aborted).
Sub Main()
Dim thread_1 As System.Threading.Thread = New Threading.Thread(AddressOf mithread)
thread_1.Start()
System.Threading.Thread.Sleep(100)
While Not thread_1.ThreadState = Threading.ThreadState.Running
Console.WriteLine(thread_1.ThreadState.ToString)
thread_1.Abort()
Console.WriteLine(thread_1.ThreadState.ToString)
If thread_1.ThreadState = Threading.ThreadState.Aborted Then Exit While
End While
End Sub
Sub mithread()
End Sub
Related
I am attempting to load thousands of URLs into a list, then simultaneously download the webpage source of all of those URLs. I thought I had a clear understanding of how to accomplish this but it seems that the process goes 1 by 1 (which is painstakingly slow).
Is there a way to make this launch all of these URLs at once, or perhaps more than 1 at a time?
Public Partial Class MainForm
Dim ImportList As New ListBox
Dim URLList As String
Dim X1 As Integer
Dim CurIndex As Integer
Public Sub New()
Me.InitializeComponent()
End Sub
Sub MainFormLoad(sender As Object, e As EventArgs)
Try
Dim lines() As String = IO.File.ReadAllLines("C:\URLFile.txt")
ImportList.Items.AddRange(lines)
Catch ex As Exception
MessageBox.Show(ex.ToString)
Finally
label1.Text = "File Loaded"
X1 = ImportList.Items.Count
timer1.Enabled = True
If Not backgroundWorker1.IsBusy Then
backgroundWorker1.RunWorkerAsync()
End If
End Try
End Sub
Sub BackgroundWorker1DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
URLList = ""
For Each item As String In ImportList.Items
CheckName(item)
CurIndex = CurIndex + 1
Next
End Sub
Sub BW1_Completed()
timer1.Enabled = False
label1.Text = "Done"
End Sub
Sub CheckName(ByVal CurUrl As String)
Dim RawText As String
Try
RawText = New System.Net.WebClient().DownloadString(CurUrl)
Catch ex As Exception
MessageBox.Show(ex.ToString)
Finally
If RawText.Contains("404") Then
If URLList = "" Then
URLList = CurUrl
Else
URLList = URLList & vbCrLf & CurUrl
End If
End If
End Try
End Sub
Sub Timer1Tick(sender As Object, e As EventArgs)
label1.Text = CurIndex.ToString & " of " & X1.ToString
If Not URLList = "" Then
textBox1.Text = URLList
End If
End Sub
Sub Button1Click(sender As Object, e As EventArgs)
Clipboard.Clear
Clipboard.SetText(URLList)
End Sub
End Class
As the title implies, I am trying to create a progress bar that updates with a file transfer. I am currently using Visual Studio 2019. I have been through dozens of articles and videos all claiming to do just this. After many days of testing, I have gotten close, but the progress bar will still only update after the file transfer is complete. I am using multi threading techniques to accomplish just this much. I would very much appreciate if someone could just lay it down for me on how to do this. Here is my code so far. It doesn't really help for making it but you can at least see what I am trying to achieve. I also left out some large chunks of commented out test script.
Summary of what I need to is: Create a script that will copy the specified directory and all sub directories. While doing this I would like the progress bar to move with the file transfer.
Imports System.ComponentModel
Imports System.Threading
Imports System
Imports System.IO
Public Class Form1
Private Sub BtnStartTransfer_Click(sender As Object, e As EventArgs) Handles btnStartTransfer.Click
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Delegate Sub DelegateProgressBarMax(ByVal check As Integer)
Private Sub ProgressBarUpdate(ByVal check As Integer)
If pBar1.InvokeRequired = True Then
Invoke(Sub() pBar1.Value = check)
Else
pBar1.Value = check
End If
End Sub
Private Delegate Sub DelegateUpdateOutput(ByVal check2 As String)
Private Sub OutputUpdate(ByVal check2 As String)
If txtOutput.InvokeRequired = True Then
Invoke(Sub() txtOutput.Text = txtOutput.Text & check2 & Environment.NewLine)
Else
txtOutput.Text = txtOutput.Text & check2
End If
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim getCopyFrom As String = txtCopyFrom.Text
Dim getCopyTo As String = txtCopyTo.Text
Dim splitUser() As String = getCopyFrom.Split("\")
Dim finalValue As String = splitUser.Length - 1
Dim stringValue As String = CStr(splitUser(finalValue))
Dim getUser As String
'If MsgBox("Is this the correct user?: " & stringValue, vbYesNo + vbQuestion) = vbYes Then
' getUser = stringValue
'Else
' getUser = InputBox("Enter in the correct Username")
'End If
Dim checkCopyFrom As New IO.DirectoryInfo(getCopyFrom)
Dim checkCopyTo As New IO.DirectoryInfo(getCopyTo)
If checkCopyFrom.Exists Then
Else
MsgBox("The location you are trying to copy from does not exist.")
Exit Sub
End If
If checkCopyTo.Exists Then
Else
MsgBox("The location you are trying to copy to does not exist.")
Exit Sub
End If
'Copying the Desktop folder
Dim dirDesktop = getCopyFrom & "\Desktop"
Dim getDir = IO.Directory.GetFiles(dirDesktop, "*", IO.SearchOption.AllDirectories)
Dim fileTotal As Integer = getDir.Length
Dim filesTransferred As Integer = 0
Dim di As New DirectoryInfo(dirDesktop)
Dim fiArr As FileInfo() = di.GetFiles("*", SearchOption.AllDirectories)
Dim diArr As DirectoryInfo() = di.GetDirectories("*", IO.SearchOption.AllDirectories)
Dim fri As FileInfo
Dim fol As DirectoryInfo
For Each fri In fiArr
filesTransferred += 1
BackgroundWorker1.ReportProgress(CInt(filesTransferred * 100 \ fiArr.Length), True)
OutputUpdate(fri.Name)
'File.Copy(dirDesktop & "\" & fri.Name, getCopyTo & "\" & fri.Name, True)
'My.Computer.FileSystem.CopyDirectory(getCopyFrom & "\Desktop", getCopyTo & "\Users\" & getUser & "\Desktop", False)
Next fri
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
pBar1.Value = e.ProgressPercentage
End Sub
I'm suffering with this VB.Net 2017 code which is supposed to check if Proxies working or not. Sometimes it reach to an end successfully, and sometimes the program never reach and end or take lots of time to do so, although I have specified the timeout for every webrequest to be 11000... Also, the list of working proxies always has duplicates! I don't know how that happens, althoug the original (raw) list is unique!
Could you please help? This is supposed to wait till the 99 threads finished then another 99 (or the remaining threads) kick-started.
P.S. MYWEBSITE.com works for me only and it displays the IP address of the visitor, i.e. to double check if the proxy has worked fine
Imports System.Net
Imports System.IO
Imports System
Imports System.Text.RegularExpressions
Imports System.Threading
Public Class frmMain
Dim FinalWorkingProxies As New List(Of String)()
Private Sub btnBrowse_Click(sender As Object, e As EventArgs) Handles btnBrowse.Click
Control.CheckForIllegalCrossThreadCalls = False
PB.Maximum = txtRawIP.Lines.Count
PB.Value = 0
StartCheckingIP(0)
End Sub
Function StartCheckingIP(ByVal num As Integer)
For I As Integer = num To txtRawIP.Lines.Count - 1
Dim StrIPOnly As String = txtRawIP.Lines(I)
StrIPOnly = Trim(StrIPOnly.TrimStart("0"c)) 'remove any leading zeros
Try
Dim clsThreads As New System.Threading.Thread(AddressOf CheckIP)
clsThreads.Start(StrIPOnly)
Catch ex As Exception
MsgBox(I)
End Try
If (I > 0 And (I Mod 99 = 0)) Then Exit For
Next
Return True
End Function
Private Function CheckIP(ByVal Prox As String) As Boolean
'txtHTML.Text += vbCrLf & Prox
'txtHTML.Refresh()
Dim txtWebResult As String = ""
Dim OriginalFullProx As String = Trim(Prox)
Dim proxyObject As WebProxy = New WebProxy("http://" & OriginalFullProx & "/")
proxyObject.BypassProxyOnLocal = True
Prox = Prox.Substring(0, Prox.IndexOf(":"))
Dim sURL As String
sURL = "http://MYWEBSITE.com/testip.php"
Dim wrGETURL As WebRequest
wrGETURL = WebRequest.Create(sURL)
wrGETURL.Proxy = proxyObject
wrGETURL.Timeout = 6000
txtWebResult = "Dosn't work"
Try
Dim objStream As Stream
objStream = wrGETURL.GetResponse.GetResponseStream
Dim objReader As New StreamReader(objStream)
Dim sLine As String = ""
sLine = objReader.ReadLine
If Not sLine Is Nothing Then
txtWebResult = sLine
End If
txtWebResult = Regex.Replace(txtWebResult, “^\s+$[\r\n]*”, “”, RegexOptions.Multiline)
If (Trim(Prox) = Trim(txtWebResult)) Then
FinalWorkingProxies.Add(OriginalFullProx)
End If
Catch ex As Exception
txtWebResult = "Dosn't work"
End Try
If (PB.Value < PB.Maximum) Then PB.Value += 1
PB.Refresh()
If (PB.Value = PB.Maximum) Then
txtFilteredIP.Clear()
Randomize()
Dim RRR As Integer = CInt(Math.Ceiling(Rnd() * 1000)) + 1
Thread.Sleep(RRR)
If (txtFilteredIP.Text <> "") Then Return False
Dim str As String
For Each str In FinalWorkingProxies
txtFilteredIP.Text += str & vbCrLf
Next
ElseIf ((PB.Value - 1) > 0 And ((PB.Value - 1) Mod 99 = 0)) Then
StartCheckingIP(PB.Value)
End If
Return True
End Function
Private Sub txtRawIP_TextChanged(sender As Object, e As EventArgs) Handles txtRawIP.TextChanged
lblRawIPTotal.Text = "Total: " & txtRawIP.Lines.Count
End Sub
Private Sub txtFilteredIP_TextChanged(sender As Object, e As EventArgs) Handles txtFilteredIP.TextChanged
lblFilteredIPTotal.Text = "Total: " & txtFilteredIP.Lines.Count
End Sub
End Class
Here is the modified code, but it stills takes long of time to finalize long list of proxies, although I sat max concurrent connection to 2000 and timeout to 8sec. Please help. Thanks.
Public Class frmMain
Dim FinalWorkingProxies As New List(Of String)()
Private Sub btnBrowse_Click(sender As Object, e As EventArgs) Handles btnBrowse.Click
'Control.CheckForIllegalCrossThreadCalls = False
ServicePointManager.Expect100Continue = False
ServicePointManager.DefaultConnectionLimit = 2000
'ServicePointManager.Expect100Continue = True
FinalWorkingProxies.Clear()
PB.Maximum = txtRawIP.Lines.Count
PB.Value = 0
StartCheckingIP(0)
End Sub
Function StartCheckingIP(ByVal num As Integer)
For I As Integer = num To txtRawIP.Lines.Count - 1
Dim StrIPOnly As String = txtRawIP.Lines(I)
StrIPOnly = Trim(StrIPOnly.TrimStart("0"c)) 'remove any leading zeros
Try
Dim clsThreads As New System.Threading.Thread(AddressOf CheckIP)
clsThreads.Start(StrIPOnly)
Catch ex As Exception
MsgBox(I)
End Try
If (I > 0 And (I Mod 333 = 0)) Then Exit For
Next
Return True
End Function
Private Function CheckIP(ByVal Prox As String) As Boolean
'txtHTML.Text += vbCrLf & Prox
'txtHTML.Refresh()
Dim txtWebResult As String = ""
Dim OriginalFullProx As String = Trim(Prox)
Dim proxyObject As WebProxy = New WebProxy("http://" & OriginalFullProx & "/")
proxyObject.BypassProxyOnLocal = True
Prox = Prox.Substring(0, Prox.IndexOf(":"))
Dim sURL As String
sURL = "http://MYWEBSITE.com/testip.php"
Dim wrGETURL As WebRequest
wrGETURL = WebRequest.Create(sURL)
wrGETURL.Proxy = proxyObject
wrGETURL.Timeout = 8000
txtWebResult = "Dosn't work"
Try
Dim objStream As Stream
objStream = wrGETURL.GetResponse.GetResponseStream
Dim objReader As New StreamReader(objStream)
Dim sLine As String = ""
sLine = objReader.ReadLine
If Not sLine Is Nothing Then
txtWebResult = sLine
End If
txtWebResult = Regex.Replace(txtWebResult, “^\s+$[\r\n]*”, “”, RegexOptions.Multiline)
If (Trim(Prox) = Trim(txtWebResult)) Then
'Now know exact country
sURL = "http://ip-api.com/xml/" & Prox
wrGETURL = WebRequest.Create(sURL)
wrGETURL.Proxy = proxyObject
wrGETURL.Timeout = 8000
objStream = wrGETURL.GetResponse.GetResponseStream
Dim objReader2 As New StreamReader(objStream)
Dim FullCODEOFAPI As String = objReader2.ReadToEnd()
Dim XMLR As XmlReader
XMLR = XmlReader.Create(New StringReader(FullCODEOFAPI))
XMLR.ReadToFollowing("country")
XMLR.Read()
OriginalFullProx += "-" + XMLR.Value
FinalWorkingProxies.Add(OriginalFullProx)
End If
Catch ex As Exception
txtWebResult = "Dosn't work"
End Try
If (PB.Value < PB.Maximum) Then UpdatePB(1)
If (PB.Value = PB.Maximum) Then
UpdateFilteredList(1)
ElseIf ((PB.Value - 1) > 0 And ((PB.Value - 1) Mod 333 = 0)) Then
StartCheckingIP(PB.Value)
End If
Return True
End Function
Private Delegate Sub UpdatePBDelegate(ByVal PBVal As Integer)
Private Sub UpdatePB(ByVal PBVal As Integer)
If PB.InvokeRequired Then
PB.Invoke(New UpdatePBDelegate(AddressOf UpdatePB), New Object() {PBVal})
Else
PB.Value += PBVal
PB.Refresh()
End If
End Sub
Private Delegate Sub UpdateFilteredListDelegate()
Private Sub UpdateFilteredList(ByVal TMP As Integer)
If txtFilteredIP.InvokeRequired Then
txtFilteredIP.Invoke(New UpdatePBDelegate(AddressOf UpdateFilteredList), New Object() {TMP})
Else
txtFilteredIP.Clear()
Dim str As String
For Each str In FinalWorkingProxies
txtFilteredIP.Text += str & vbCrLf
Next
End If
End Sub
Private Sub txtRawIP_TextChanged(sender As Object, e As EventArgs) Handles txtRawIP.TextChanged
lblRawIPTotal.Text = "Total: " & txtRawIP.Lines.Count
End Sub
Private Sub txtFilteredIP_TextChanged(sender As Object, e As EventArgs) Handles txtFilteredIP.TextChanged
lblFilteredIPTotal.Text = "Total: " & txtFilteredIP.Lines.Count
End Sub
Private Sub btnLoadList_Click(sender As Object, e As EventArgs) Handles btnLoadList.Click
OFD.ShowDialog()
If (OFD.FileName <> "") Then
txtRawIP.Text = File.ReadAllText(OFD.FileName)
End If
End Sub
End Class
I am creating a fairly simple ping tool which shows in milliseconds how long the server took to respond. If the server does not respond, it shows as it responded in 0ms. I wanted to implement an If statement to write Server failed to respond in the ListBox rather than it replied in 0ms. The only problem with this is I have a chunk of code which need to be run outside the If but continues inside the If and involves using the line of code Next... This seems to cause the If statement to not recognise the End If and the End If to not recognise the If...
Here is my code:
For i As Integer = 0 To numberOfPings - 1
Dim ping As New Ping
Dim pingRe As PingReply = ping.Send(pingTarget)
If pingRe.RoundtripTime = 0 Then
Me.listboxPing.Items.Add("Server failed to respond...")
Else
Me.listboxPing.Items.Add("Response from " & pingTarget & " in " & pingRe.RoundtripTime.ToString() & "ms")
listboxPing.SelectedIndex = listboxPing.Items.Count - 1
listboxPing.SelectedIndex = -1
Application.DoEvents()
Threading.Thread.Sleep(500)
Next
Me.listboxPing.Items.Add("")
End If
Does anyone know of a way I could fix this/get around this issue?
Thanks,
If I were going to write code to ping an address and show the results it would look something like this.
Dim pingThrd As Threading.Thread
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If pingThrd Is Nothing OrElse pingThrd.ThreadState = Threading.ThreadState.Stopped Then
RichTextBox1.Clear()
pingThrd = New Threading.Thread(AddressOf PingIt)
pingThrd.IsBackground = True
pingThrd.Start("192.168.33.1")
End If
End Sub
Public Sub PingIt(pingTarget As Object)
Dim numberOfPings As Integer = 5
Dim pingT As String = DirectCast(pingTarget, String)
Dim pingTimeOut As Integer = 1000
Const dlyBetweenPing As Integer = 500
Dim dspStr As String
For i As Integer = 0 To numberOfPings - 1
Dim pingit As New Ping
Dim pingRe As PingReply = pingit.Send(pingT, pingTimeOut)
'check if success
If pingRe.Status = IPStatus.Success Then
dspStr = String.Format("Response from: {0} in {1}ms.", pingRe.Address, pingRe.RoundtripTime)
Else
dspStr = String.Format("{0} failed. Status: {1}", pingRe.Address, pingRe.Status)
End If
Me.BeginInvoke(Sub()
RichTextBox1.AppendText(dspStr)
RichTextBox1.AppendText(Environment.NewLine)
End Sub)
Threading.Thread.Sleep(dlyBetweenPing)
Next
End Sub
edit: Same basic code but allow thread to start with different address and count.
Structure PingWhat
Dim addr As String
Dim howmany As Integer
End Structure
Dim pingThrd As Threading.Thread
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If pingThrd Is Nothing OrElse pingThrd.ThreadState = Threading.ThreadState.Stopped Then
RichTextBox1.Clear()
'setup a thread to do the actual ping'ing
'this allows the UI to function
pingThrd = New Threading.Thread(AddressOf PingIt)
pingThrd.IsBackground = True
'setup address to ping and howmany times to ping it
Dim somePing As New PingWhat With {.addr = "192.168.33.1", .howmany = 3}
'start the thread
pingThrd.Start(somePing)
End If
End Sub
Public Sub PingIt(pingTarget As Object)
Dim pingT As PingWhat = DirectCast(pingTarget, PingWhat)
Dim pingTimeOut As Integer = 1000
Const dlyBetweenPing As Integer = 500
Dim dspStr As String
For i As Integer = 1 To pingT.howmany
Dim pingit As New Ping
Dim pingRe As PingReply = pingit.Send(pingT.addr, pingTimeOut)
'check if success
If pingRe.Status = IPStatus.Success Then
dspStr = String.Format("Response from: {0} in {1} ms.", pingRe.Address, pingRe.RoundtripTime)
Else
dspStr = String.Format("Ping Failed {0}. Status: {1}", pingT.addr, pingRe.Status)
End If
'update the UI
Me.BeginInvoke(Sub()
RichTextBox1.AppendText(dspStr)
RichTextBox1.AppendText(Environment.NewLine)
RichTextBox1.ScrollToCaret()
End Sub)
Threading.Thread.Sleep(dlyBetweenPing)
Next
Me.BeginInvoke(Sub()
RichTextBox1.AppendText("Done")
RichTextBox1.AppendText(Environment.NewLine)
RichTextBox1.ScrollToCaret()
End Sub)
End Sub
Is this what you're after?
For i As Integer = 0 To numberOfPings - 1
Dim ping As New Ping
Dim pingRe As PingReply = ping.Send(pingTarget)
If pingRe.RoundtripTime = 0 Then
Me.listboxPing.Items.Add("Server failed to respond...")
Else
Me.listboxPing.Items.Add("Response from " & pingTarget & " in " & pingRe.RoundtripTime.ToString() & "ms")
listboxPing.SelectedIndex = listboxPing.Items.Count - 1
listboxPing.SelectedIndex = -1
Application.DoEvents()
Threading.Thread.Sleep(500)
add = True
Exit For
End If
Next
If add Then Me.listboxPing.Items.Add("")
The If will change the scope, therefore, you need to use a variable to check whether it went into the Else part.
Of course, you need to close the first If before the Next.
#dbasnett This was the code I using before and it was absolutely perfect for what i needed EXCEPT if a ping failed it would just say (PingTarget) responded in 0ms which is not ideal. Ideally i would like it to say Server failed to respond... . Do you know a way in which this can be achieved by modifying my original code?
Imports System.Net.NetworkInformation
Imports System.Runtime.InteropServices
Public Class PingClient
Private Const EM_SETCUEBANNER As Integer = &H1501
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As String) As Int32
End Function
Private Sub SetCueText(ByVal control As Control, ByVal text As String)
SendMessage(control.Handle, EM_SETCUEBANNER, 0, text)
End Sub
Private Sub PingClient_Load(sender As Object, e As EventArgs) Handles MyBase.Load
SetCueText(textboxIP, "IP Address/Domain")
SetCueText(textboxPing, "No. Of Pings")
End Sub
Structure PingWhat
Dim addr As String
Dim howmany As Integer
End Structure
Dim pingThrd As Threading.Thread
Public Sub buttonPing_Click(sender As Object, e As EventArgs) Handles buttonPing.Click
If pingThrd Is Nothing OrElse pingThrd.ThreadState = Threading.ThreadState.Stopped Then
Dim pingTarget As String = ""
Dim numberOfPings As Integer = 0
Dim intTimeout As Integer = 2000
If String.IsNullOrEmpty(textboxIP.Text) Then
MsgBox("You must enter an IP Address or Domain.")
Exit Sub
End If
If Not Int32.TryParse(textboxPing.Text, numberOfPings) Then
MsgBox("You must enter a number of how many times the target address will be pinged.")
Exit Sub
End If
If numberOfPings = 0 Then
MsgBox("You must enter a value over 0.")
textboxPing.Clear()
Exit Sub
End If
'setup a thread to do the actual ping'ing
'this allows the UI to function
pingThrd = New Threading.Thread(AddressOf PingIt)
pingThrd.IsBackground = True
'setup address to ping and howmany times to ping it
Dim somePing As New PingWhat With {.addr = pingTarget, .howmany = numberOfPings}
'start the thread
pingThrd.Start(somePing)
End If
Me.listboxPing.Items.Add("")
End Sub
Public Sub PingIt(pingTarget As Object)
Dim pingT As PingWhat = DirectCast(pingTarget, PingWhat)
Dim pingTimeOut As Integer = 1000
Const dlyBetweenPing As Integer = 500
Dim dspStr As String
For i As Integer = 1 To pingT.howmany
Dim pingit As New Ping
Dim pingRe As PingReply = pingit.Send(pingT.addr, pingTimeOut)
'check if success
If pingRe.Status = IPStatus.Success Then
dspStr = String.Format("Response from: {0} in {1} ms.", pingRe.Address, pingRe.RoundtripTime)
Else
dspStr = String.Format("Ping Failed {0}. Status: {1}", pingT.addr, pingRe.Status)
End If
'update the UI
Me.BeginInvoke(Sub()
listboxPing.Items.Add(dspStr)
End Sub)
Threading.Thread.Sleep(dlyBetweenPing)
Next
Me.BeginInvoke(Sub()
listboxPing.Items.Add("Done")
End Sub)
End Sub
Private Sub PingClient_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
Dim Response As Integer
Response = MsgBox("Are you sure you want to exit the Ping Tool?", 36)
If Response = MsgBoxResult.Yes Then
Else
e.Cancel = True
End If
End Sub
End Class
I have 2 projects, one which has a highscorelist stored on it, and one which tries to add highscores to that list and retrieve all items on the list. Trying to put items on the list works good, but retrieving the list doesn't work well. Here's the code:
Option Strict On
Option Explicit On
Imports System.Net.Sockets
Imports System.Threading
Public Class Main
Dim server As New TcpListener(45888)
Dim client As New TcpClient
Dim stream As NetworkStream
Dim connected As Boolean
Private Sub cmd_start_Click(sender As Object, e As EventArgs) Handles cmd_start.Click
server.Start()
cmd_start.Enabled = False
cmd_stop.Enabled = True
lbl_status.Text = "Running"
lbl_status.ForeColor = Color.Green
tmr.Start()
End Sub
Private Sub cmd_stop_Click(sender As Object, e As EventArgs) Handles cmd_stop.Click
server.Stop()
cmd_start.Enabled = True
cmd_stop.Enabled = False
lbl_status.Text = "Not running"
lbl_status.ForeColor = Color.Red
tmr.Stop()
End Sub
Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
connected = False
CheckForIllegalCrossThreadCalls = False
End Sub
Dim x As Integer = 0
Private Sub tmr_Tick(sender As Object, e As EventArgs) Handles tmr.Tick
If server.Pending Then
client = server.AcceptTcpClient()
stream = client.GetStream()
tmr.Stop()
read()
Else
tmr.Start()
End If
lbl_mseconds.Text = "Relative time: " & x
x += 1
End Sub
Private Sub SendMessage(message As String)
Dim sendtext() As Byte = System.Text.Encoding.ASCII.GetBytes(message)
stream.Write(sendtext, 0, sendtext.Length)
stream.Flush()
End Sub
Private Sub read()
Dim rec(client.ReceiveBufferSize) As Byte
stream.Read(rec, 0, client.ReceiveBufferSize)
Dim rectext As String = System.Text.Encoding.ASCII.GetString(rec)
If rectext.Contains("#1#") Then
rectext = rectext.Substring(3)
If rectext.Split(CChar("-"))(0).Length = 2 Then rectext = "0" & rectext
If rectext.Split(CChar("-"))(0).Length = 1 Then rectext = "00" & rectext
listbox_highscores.Items.Add(rectext)
ElseIf rectext.Contains("#2#") Then
Dim tosend As String = listbox_highscores.Items(0).ToString
For i = 1 To listbox_highscores.Items.Count - 1
tosend &= "," & listbox_highscores.Items(i).ToString
Next
MsgBox(tosend)
SendMessage(tosend)
End If
tmr.Start()
End Sub
End Class
On the other project I have this:
Dim server As New TcpListener(45888)
Dim client As New TcpClient
Dim stream As NetworkStream
Friend Sub sendHighscore(name As String, score As Integer)
Try
client.Connect("192.168.1.127", 45888)
Catch ex As Exception
Exit Sub
End Try
stream = client.GetStream()
Dim sendtext() As Byte = Encoding.ASCII.GetBytes("#1#" & score & "-" & name)
stream.Write(sendtext, 0, sendtext.Length)
client = New TcpClient
End Sub
Friend Sub getHighscoreList()
ListBox_highscores.Items.Clear()
Try
client.Connect("192.168.1.127", 45888)
Catch ex As Exception
ListBox_highscores.Items.Add("Couldn't connect")
Exit Sub
End Try
stream = client.GetStream()
Dim sendtext() As Byte = Encoding.ASCII.GetBytes("#2#")
stream.Write(sendtext, 0, sendtext.Length)
client = New TcpClient
read()
End Sub
Private Sub read()
Dim rec(client.ReceiveBufferSize) As Byte
stream.Read(rec, 0, client.ReceiveBufferSize)
Dim rectext As String = Encoding.ASCII.GetString(rec)
Label2.Text = rectext
For Each item In rectext.Split(",")
ListBox_highscores.Items.Add(item)
Next
End Sub
Then when I use the sub sendHighscore() with a name and score, everything perfectly works and it shows in the other project on the list, but when I use the sub getHighscoreList() the list on the second project only contains the first item from the first list. Does someone has ideas?
Edit: Original answer removed entirely because it wasn't actually the problem (although it did offer improvements). My answer was nearly identical to this one anyway.
After analyzing this project much more closely, the problem with the For..Next loop not returning the expected results is because the strings are being sent back and forth as byte arrays in buffers much larger than necessary (client.ReceiveBufferSize). The actual "strings" received contain large amounts of non-printable characters (garbage) added to the end to fill the buffer. The quick and dirty solution is to remove all non-printable characters:
rectext = System.Text.RegularExpressions.Regex.Replace(rectext, _
"[^\u0020-\u007F]", String.Empty)
The whole Sub would read like this:
Private Sub read()
Dim rec(client.ReceiveBufferSize) As Byte
stream.Read(rec, 0, client.ReceiveBufferSize)
Dim rectext As String = System.Text.Encoding.ASCII.GetString(rec)
If rectext.Contains("#1#") Then
rectext = rectext.Substring(3)
If rectext.Split(CChar("-"))(0).Length = 2 Then rectext = "0" & rectext
If rectext.Split(CChar("-"))(0).Length = 1 Then rectext = "00" & rectext
rectext = System.Text.RegularExpressions.Regex.Replace(rectext, "[^\u0020-\u007F]", String.Empty)
listbox_highscores.Items.Add(rectext)
ElseIf rectext.Contains("#2#") Then
Dim tosend As String = listbox_highscores.Items(0).ToString
For i As Integer = 1 To (listbox_highscores.Items.Count - 1)
tosend &= "," & listbox_highscores.Items(i).ToString
Next
SendMessage(tosend)
End If
tmr.Start()
End Sub
Try this, your comma's are off as well...
Dim tosend As String = String.Empty
Dim intCount As Integer = 0
For i As Integer = 0 To listbox.Items.Count - 1
If intCount >= 1 Then
tosend &= "," & listbox.Items(i).ToString
Else
tosend &= listbox.Items(i).ToString
intCount += 1
End If
Next
MessageBox.Show(tosend)
Screenshot THAT IT WORKS!