Join 149,911 VB.NET Programmers for FREE! Get instant access to thousands of VB.NET experts, tutorials, code snippets, and more! There are 2,177 people online right now. Registration is fast and FREE... Join Now!
I need to start loading my data on the mainform while the splash screen makes the user wait
My question is,
Do I declare thread1 in the splashscreen form or do I declare both threads in the main form load area?
Thank You...
Here is splash screen code..I declared th1 as current thread which i assume is the loading of the splash screen th2 is a sub in the main form which loads after the splash
CODE
Imports System.Threading Public NotInheritable Class SplashScreen1 Public th1 As Thread Public th2 As Thread Private Sub splash_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load th1 = Thread.CurrentThread th2 = New Thread(AddressOf frmPortland.DownloadPageOregon) Timer1.Start() End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick If (Me.ProgressBar1.Value < 100) Then Me.ProgressBar1.Value += 1 Else Me.Timer1.Enabled = False Me.Hide() End If
If (Me.ProgressBar1.Value = 10) Then Dim frm As New frmPortland th2.Start() End If End Sub
End Class
So far I am able to get both started but am getting a cross-threading error when the sub is processing on the main form
Did lots of research on this last night and I now realize that I cant use My Beginning VB.Net books for this This is an advanced topic and it means alot to me to understand it (at least partially anyway)
Also, I need to know if the doevents() call is needed here and where do i put that?
This post has been edited by Schmit38: 23 Jan, 2008 - 09:46 AM
There's no problem as such with your current code (although I would do it a completely different way), your problem is actually where you are trying to do stuff to your form from th2 in frmPortland.DownloadPageOregon. Because your form actually runs on th1. You can get around this problem by using Invoke. If you show the code in frmPortland.DownloadPageOregon then I can show you how to change it.
Or somebody else will. Whoever feels nicest at the time they see it
DownloadPage() 'ListView1.Visible = False Me.Text = "Multnomah County Round-Up" 'lblTime.Visible = False 'DownloadPage() ' Set to Details view. Me.ListView1.View = View.Details ' Add columns using the ColHeader class. The fourth ' parameter specifies true for an ascending sort order. ListView1.Columns.Add(New ColHeader("Station", 110, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Temp", 45, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("High", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Low", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Chg", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Prec.", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Elev", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Time", 60, HorizontalAlignment.Center, True))
Me.Controls.Add(Me.ListView1)
AddHandler Me.ListView1.ColumnClick, AddressOf ListView1_ColumnClick ListView1.BringToFront() Dim currenttime As String Dim s As String Dim t As String currenttime = Date.Now.ToString t = currenttime.IndexOf("2008") s = currenttime.Substring(t + 4, 6) s = s.Trim If s(4) = ":" Then s = currenttime.Substring(t + 4, 5) s = s.Trim
End If Dim ampm As String ampm = currenttime.Substring(currenttime.Length - 2)
Dim CPUtime As String CPUtime = s & ampm txtTime.Text = "Multnomah County observations at " & CPUtime
End Sub
Sub DownloadPage()
Dim S As String ListView1.Items.AddRange(New ListViewItem() {s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23}) 's3
' Dim objreader As StreamReader = New StreamReader("C:\Clark.txt", False) 'CutData = objreader.ReadToEnd
'Move string position to first record Position = data.IndexOf("Current Weather Summary for OREGON") '148552 'CityNameLength = Length 'Cut any code out prior to that spot CutData = data.Substring(Position) '485334
S = CutData.IndexOf("University of Utah") CutData = CutData.Substring(0, S) ' textData.Text = CutData '632960 ' MsgBox(CutData.Length)
'Dim objWriter As StreamWriter = New StreamWriter("C:\Clark.txt", False) 'objWriter.Write(CutData) 'objWriter.Close() 'objWriter = Nothing
'CityName = txtSearch.Text.ToUpper()
LoadData()
' label90.BackColor = Color.Transparent
End Sub
Sub LoadData() y = 0
Dim slash1 As Integer Dim slash2 As Integer Dim slash3 As Integer Dim slash4 As Integer Dim slash5 As Integer Dim i As Integer
For i = 1 To 23
Here: Position = CutData.IndexOf(Cities(i)) If Position = -1 Then y = y + 1 If y = 1 Then ListView1.Items.RemoveAt(i - 1) End If If y = 2 Then ListView1.Items.RemoveAt(i - y) End If If i < 23 Then i = i + 1 GoTo Here End If
End If
Try SubStr = CutData.Substring(Position, 990) Catch ex As ArgumentOutOfRangeException 'MsgBox(Cities(i) & " station is not reporting") End Try
Elev = StationString.Substring(slash4, 4) If Elev.IndexOf(">") <> -1 Then Elev = StationString.Substring(slash4 + 1, 5) End If If Elev.IndexOf("&") <> -1 Then Dim a As String a = Elev.IndexOf("&") Elev = Elev.Substring(0, a) End If
Elev = CInt(Elev)
If Val(Elev) < 100 Then Elev = " " & Elev End If
Elev = CInt(Elev) If Elev < 1000 Then Elev = " " + Elev
Dwpt = StationString.Substring(slash5, 12) Dim Begin As Integer Dim EndPos As Integer Begin = Dwpt.IndexOf(">") EndPos = Dwpt.IndexOf("<") Dwpt = Dwpt.Substring(Begin + 1, EndPos - 1)
If Dwpt = "-" Then Dwpt = "" End If Dwpt = Dwpt.TrimStart()
If Wind.IndexOf(">") <> -1 Then SS = Wind.IndexOf(">") Wind = Wind.Substring(SS + 1) End If If Wind.LastIndexOf("<") <> -1 Then WW = Wind.LastIndexOf("<") Wind = Wind.Substring(0, WW) End If Wind.Trim() If Wind = "-" Then Wind = "" If Wind = Nothing Then Wind = "0" End If End If slash1 = StationString.IndexOf(">", slash5) slash2 = StationString.IndexOf(">", slash1 + 1) slash3 = StationString.IndexOf(">", slash2 + 1) slash4 = StationString.IndexOf(">", slash3 + 1) slash5 = StationString.IndexOf(">", slash4 + 1) '356
Direction = StationString.Substring(slash5 - 1, 5) If Direction.IndexOf(">") <> -1 Then SS = Direction.IndexOf(">") Direction = Direction.Substring(SS + 1) End If If Direction.LastIndexOf("<") <> -1 Then WW = Direction.LastIndexOf("<") Direction = Direction.Substring(0, WW) End If Direction.Trim() If Direction = "-" Then Direction = "" End If If Wind = "-" Then Direction = "" End If
If PeakWind.IndexOf(">") <> -1 Then SS = PeakWind.IndexOf(">") PeakWind = PeakWind.Substring(SS + 1) End If If PeakWind.LastIndexOf("<") <> -1 Then WW = PeakWind.LastIndexOf("<") PeakWind = PeakWind.Substring(0, WW) End If PeakWind.Trim() If PeakWind = "-" Then PeakWind = "0" End If If PeakWind = "" Then PeakWind = "0" End If PeakWind.Trim() If Val(PeakWind) < 10 Then PeakWind = "0" End If Wind = Wind.Trim() Wind = Wind.TrimStart() PeakWind = PeakWind.Trim() PeakWind.TrimStart() Wind.Trim() If Val(Wind) = 0 Then Wind = "" End If PeakWind.Trim() If Val(PeakWind) = 0 Then PeakWind = "" End If
If PeakWind <> "0" And PeakWind <> "" Then PeakWind = " G" & PeakWind
End If
WDSP = (Direction & " " & Wind & PeakWind)
End If
This post has been edited by Schmit38: 23 Jan, 2008 - 08:11 PM
When you do threads you have to start thinking parallel processing. We showed you how to process in the background using one thread, the rest of your forms and such are on another thread.
To keep things simple don't do too much with the background thread we had setup for you. Keep everything going on the main thread.
And btw... DoEvents is just fine if you know how to use it.
Martyr is of course correct. You don't need to do threading for the sake of threading.
But learning how to access controls from another thread is something you'll probably have to do sooner or later, so you may as well learn now.
You also haven't shown the code for the function DownloadPageOregon() !!
Because inside that function, (from what I assume) you are trying to access some controls on the form. I need to see that code, so I can show you how to use Invoke to do what you are trying to do.
If the thread is constantly accessing the controls, then it should probably not be in that thread.
But this is all conjecture until I see that code. Then we can see whether or not it deserves to have another thread.
As for where you declare the threads, well that really depends on the context of the thread. Where and why is it going to be used?
--- Though personally, I don't see much use for the DoEvents function; if something is going to run for a long time, it may as well run in a thread.
Dim request As WebRequest = WebRequest.Create(uri) Dim response As WebResponse = request.GetResponse() builder = New StringBuilder builder.Append("Request type: " & request.GetType().ToString() & vbCrLf) builder.Append("Response type: " & response.GetType().ToString() & vbCrLf) builder.Append("Content length: " & response.ContentLength & _ " bytes" & vbCrLf) builder.Append("Content type: " & response.ContentType & vbCrLf) 'MsgBox(builder.ToString())
Dim stream As Stream = response.GetResponseStream() Dim reader As New StreamReader(stream) System.Windows.Forms.Application.DoEvents() data = reader.ReadToEnd()
reader.Close() stream.Close() response.Close() End Sub
This post has been edited by PsychoCoder: 24 Jan, 2008 - 10:04 PM
No, DoEvents will not work in this situation, because the pausing is actually happening on the lines
CODE
Dim response As WebResponse = request.GetResponse() 'AND reader.ReadToEnd()
The first, because it is waiting for an HTTP response, and the second because it is waiting for the data to download.
Your only choice is to put it in another thread. This is fairly easy. When you call DownloadPageOregon, do it like this:
CODE
Dim oregonThread As New Threading.Thread(AddressOf DownloadPageOregon)
oregonThread.Start()
The oregonThread object will continue to exist, until the sub, DownloadPageOregon has completed.
When you want to pass the data back to the user interface, you must use Invoke. (Actually, in VS2003 you don't have to, but funny things will happen if you don't. In VS'05 and 08 it is a requirement)
You can do it by making a delegate and a sub:
CODE
Delegate Sub dDataReady(ByVal text As String)
Sub DataReady(ByVal text As String) TextBox1.Text = text End Sub
I've changed the code in your sub, so that it will work:
CODE
Sub DownloadPageOregon()
Dim uri As New Uri("http://www.met.utah.edu/cgi-bin/droman/raws_ca_monitor.cgi?state=OR&rawsflag=290") Dim builder As New StringBuilder
Dim stream As Stream = response.GetResponseStream()
Dim reader As New StreamReader(stream)
' I made a new variable, because it is dangerous to access variables across different threads. Dim text As String = reader.ReadToEnd()
reader.Close() stream.Close() response.Close()
'Here we are basically calling DataReady(text) 'But we have to do this funny stuff because of 'the requirements of Invoke and BeginInvoke. 'In my opinion they should build it in the syntax Dim arguments(0) As String arguments(0) = text
'This line makes the code run in the same thread as Me (which is the Form) Me.BeginInvoke(New dDataReady(AddressOf DataReady), arguments) End Sub
I've even tested it
This post has been edited by Nayana: 24 Jan, 2008 - 11:10 PM
The only problem I am having now is the fact that I want to call DownloadPageOregon when the splash screen progress bar begins. When I try to start the thread from the splash screen form I get an error on this line
And error message says: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
How would I change the splash screen code to start the thread there? Would I have to move the current code you gave me from DownloadPageOregon?
As it stands now, both threads run fine since your code fix. But the DownloadPageOregon thread only starts after the progress bar is finished. Wonder if I should move the Me.BeginInvoke statement to the splash form instead?
Its was rather confusing trying to debug two threads running at once. Guess I need to learn thread tracing.
This post has been edited by Schmit38: 25 Jan, 2008 - 08:04 PM
From looking at your code, it would appear that the thread starts soon after the value of your progress bar is 10. The point is that it takes a long time to finish, so it will probably finish after your progress bar has already reached 100.
You could probably make it appear to finish around the same time, by making your progress bar go slower.
Moving the Me.BeginInvoke to the splash screen will not make it go any faster.
Still not able to get DownloadPageOregon data stream THREAD to load while progress bar does its thing. Seems as though the thread is still not starting until the progress bar is finished. Below is the code which has been edited for me by Nayana . I am sure I have something in the wrong place
Splash screen , I want the Oregon thread to kick off when the progress bar reaches 10%
CODE
Imports System.Threading Public NotInheritable Class SplashScreen1 Private Sub splash_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Timer1.Start() End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick If (Me.ProgressBar1.Value < 100) Then Me.ProgressBar1.Value += 1 Else Me.Timer1.Enabled = False Me.Hide() End If If (Me.ProgressBar1.Value = 10) Then Dim frm As New frmPortland End If End Sub End Class
Below is the frmPortland_loading event which should start in the loading as a seperate background thread while the progress bar is moving
CODE
Private Sub frmPortland_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim oregonThread As New Threading.Thread(AddressOf Me.DownloadPageOregon) oregonThread.Start() DownloadPageOregon()
'ListView1.Visible = False Me.Text = "Multnomah County Round-Up" 'lblTime.Visible = False 'DownloadPage() ' Set to Details view. Me.ListView1.View = View.Details ' Add columns using the ColHeader class. The fourth ' parameter specifies true for an ascending sort order. ListView1.Columns.Add(New ColHeader("Station", 110, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Temp", 45, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("High", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Low", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Chg", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Prec.", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Elev", 40, HorizontalAlignment.Center, True)) ListView1.Columns.Add(New ColHeader("Time", 60, HorizontalAlignment.Center, True))
Me.Controls.Add(Me.ListView1)
AddHandler Me.ListView1.ColumnClick, AddressOf ListView1_ColumnClick ListView1.BringToFront() Dim currenttime As String Dim s As String Dim t As String currenttime = Date.Now.ToString t = currenttime.IndexOf("2008") s = currenttime.Substring(t + 4, 6) s = s.Trim If s(4) = ":" Then s = currenttime.Substring(t + 4, 5) s = s.Trim
End If Dim ampm As String ampm = currenttime.Substring(currenttime.Length - 2)
Dim CPUtime As String CPUtime = s & ampm txtTime.Text = "Multnomah County observations at " & CPUtime
' loadgrid()
End Sub
And here is the delegate sub used
CODE
Delegate Sub dDataReady(ByVal text As String)
Sub DataReady(ByVal text As String) pagestream = text End Sub
Here is the DownloadPageOregon Sub()
CODE
Sub DownloadPageOregon()
Dim uri As New Uri("http://www.met.utah.edu/cgi-bin/droman/raws_ca_monitor.cgi?state=OR&rawsflag=290") Dim builder As New StringBuilder