|
-
Apr 24th, 2004, 05:28 PM
#1
Thread Starter
Lively Member
Control invalidated on new thread start.
Why is that? I have an Outlook style bar (ComponentOne) and whenever I click on a button on my form (whether or not it's in the toolbar is irrelevant) that starts a new thread with a call to a private sub in my form, the toolbar is invalidated and won't refresh after the thread has completed. While I can add code to refresh it after the thread completes, I can't figure out how to refresh it BEFORE the thread completes (that's my goal), and any attempt to do this is ignored.
Again, the control will only refresh after the thread has completed and only if I tell it to do so.
I have tried inserting code immediately after the thread is started to refresh just the control or the whole form, and I'm still not having much luck. Does anyone out there have any idea why?
Thanks in advance,
KT
-
Apr 24th, 2004, 05:52 PM
#2
Thread Starter
Lively Member
Ok, apparently that control isn't the only one being invalidated. I have a progress bar on the form that's having the same problem. So I think I need a timer or something to refresh a few or all of the controls (at least the ones I am having trouble with) every so often while the thread is executing. Any ideas on how I can do that? Never done it before.
-
Apr 24th, 2004, 06:07 PM
#3
It sounds like you are doing something funky with the threading. You may want to post that part of the code. Also keep in mind that all UI is on the same thread, if it is being altered in another thread it will still be marshalled over to the main or UI thread when it goes to update an UI elements like controls. So be careful when using threading because lots of marshalling can actually slow the application down and ruin the whole point of multithreading.
-
Apr 24th, 2004, 07:04 PM
#4
Thread Starter
Lively Member
Ready for this?
Ok. But first, I must apologize for the coding style as I'm still learning.
I click a button on my form that corresponds to a section. For instance, "Games."
VB Code:
Private Sub showGames_Click(ByVal sender As System.Object, ByVal e As C1.Win.C1Command.ClickEventArgs) Handles showGames.Click
navBar.Enabled = False
sectionSelected = 2
Label2.Text = "Games"
Dim viewThread As New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf Me.UpdateView))
viewThread.Start()
Which calls this:
VB Code:
Private Sub UpdateView()
If sectionSelected = 1 Then
'omitted as I'm still working on this.
ElseIf sectionSelected = 2 Then
view.ParseTable(gamesTable, ListView1, mainBar)
ElseIf sectionSelected = 3 Then
view.ParseTable(moviesTable, ListView1, mainBar)
ElseIf sectionSelected = 4 Then
view.ParseTable(showsTable, ListView1, mainBar)
ElseIf sectionSelected = 5 Then
view.ParseTable(animeTable, ListView1, mainBar)
ElseIf sectionSelected = 6 Then
view.ParseTable(musicTable, ListView1, mainBar)
ElseIf sectionSelected = 7 Then
view.ParseTable(appsTable, ListView1, mainBar)
ElseIf sectionSelected = 8 Then
view.ParseTable(comicsTable, ListView1, mainBar)
ElseIf sectionSelected = 9 Then
view.ParseTable(macTable, ListView1, mainBar)
ElseIf sectionSelected = 10 Then
view.ParseTable(miscTable, ListView1, mainBar)
End If
navBar.Enabled = True
End Sub
Here's the ViewManager class that contains the ParseTable sub (called by the instance "view" as shown above):
VB Code:
Public Class ViewManager
Public Sub ParseTable(ByVal table As DataTable, ByVal list As ListView, ByVal _
progress As ProgressBar)
list.Visible = False
list.Items.Clear()
Dim rows As DataRowCollection
Dim row As DataRow
rows = table.Rows
progress.Maximum = rows.Count
For Each row In rows
Dim lvi As New ListViewItem(CType(row(1), String))
lvi.SubItems.Add(CType(row(2), String))
lvi.SubItems.Add(CType(row(3), String))
lvi.SubItems.Add(CType(row(5), String))
lvi.SubItems.Add(CType(row(6), String))
lvi.SubItems.Add(CType(row(7), String))
lvi.SubItems.Add(CType(row(8), String))
list.Items.Add(lvi)
progress.Value += 1
Next row
list.Visible = True
progress.Visible = False
progress.Value = 0
End Sub
End Class
And that's that, right? But what about the tables that are being loaded into the listview? Well, there's another button on my form called "Update Section."
VB Code:
Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonUpdate.Click
navBar.Enabled = False
mainBar.Visible = True
ListView1.Visible = False
Dim updateThread As New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf Me.updateTable))
updateThread.Start()
The updateTable() sub is almost identical to the updateView() sub shown above, the only exceptions being.. well, I'll show you:
VB Code:
Private Sub updateTable()
buttonUpdate.Enabled = False
If sectionSelected = 1 Then
' again I'm still working on the newslister function as the news section is different from other sections, such as games.
newsTable = newsLister.List(newsUrl)
ElseIf sectionSelected = 2 Then
gamesTable = sectionLister.List(gamesUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 3 Then
moviesTable = sectionLister.List(moviesUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 4 Then
showsTable = sectionLister.List(showsUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 5 Then
animeTable = sectionLister.List(animeUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 6 Then
musicTable = sectionLister.List(musicUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 7 Then
appsTable = sectionLister.List(appsUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 8 Then
comicsTable = sectionLister.List(comicsUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 9 Then
macTable = sectionLister.List(macUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
ElseIf sectionSelected = 10 Then
miscTable = sectionLister.List(miscUrl, Me.mainBar, Me.Label1)
Me.UpdateView()
End If
navBar.Enabled = True
buttonUpdate.Enabled = True
End Sub
And finally, in case you're curious, here's the sectionLister.List function that is called above.
VB Code:
Public Class SectionLister
Dim lastEntry As Boolean = False
Dim nextEntry As Integer
Dim lastItem As Boolean = False
Dim nextItem As Integer
Dim torrentTable As DataTable
Dim subProgress As ProgressBar
Dim subLabel As Label
Function List(ByVal sectionUrl As String, ByVal subProgress As ProgressBar, ByVal subLabel As Label) As DataTable
torrentTable = New DataTable
Dim _id As DataColumn = New DataColumn("ID")
_id.DataType = System.Type.GetType("System.Int32")
torrentTable.Columns.Add(_id)
Dim _time As DataColumn = New DataColumn("Time")
_time.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_time)
Dim _section As DataColumn = New DataColumn("Section")
_section.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_section)
Dim _name As DataColumn = New DataColumn("Name")
_name.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_name)
Dim _url As DataColumn = New DataColumn("URL")
_url.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_url)
Dim _size As DataColumn = New DataColumn("Size")
_size.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_size)
Dim _seeds As DataColumn = New DataColumn("Seeds")
_seeds.DataType = System.Type.GetType("System.Int32")
torrentTable.Columns.Add(_seeds)
Dim _peers As DataColumn = New DataColumn("Peers")
_peers.DataType = System.Type.GetType("System.Int32")
torrentTable.Columns.Add(_peers)
Dim _quality As DataColumn = New DataColumn("Quality")
_quality.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_quality)
Dim _donor As DataColumn = New DataColumn("Donor")
_donor.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_donor)
Dim _donorrank As DataColumn = New DataColumn("Donor Rank")
_donorrank.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_donorrank)
Dim _info As DataColumn = New DataColumn("Info URL")
_info.DataType = System.Type.GetType("System.String")
torrentTable.Columns.Add(_info)
Dim getsubs As New SubsectionLister
Dim http As New Connecter
Dim subsectionList As Hashtable = getsubs.List(sectionUrl)
subProgress.Maximum = subsectionList.Count
Dim entry As DictionaryEntry
For Each entry In subsectionList
Dim url As String = CType(entry.Value, String)
Dim title As String = CType(entry.Key, String)
subProgress.Update()
subProgress.Value += 1
subLabel.Text = "Listing: " & title
Dim html As String = http.Download(url)
ListSingleSection(html)
Next entry
subProgress.Value = 0
subLabel.Text = ""
Return torrentTable
End Function
There's more child functions under this one but I omitted them because, quite frankly, they're boring and I'm positive they have nothing to do with the problem I'm experiencing. I should note that you can actually see how I implemented the progress bar as you suggested to me in another post. I'm a quick learner, but again I must stress I've only been learning how to program for only a month, so I must apologize if the code isn't to standard. But, it's not bad for a month of learning, right?
Progress bar works great, although it has some strange quirks like I'm experiencing with the navBar (ComponentOne Outlook style bar). At first I wasn't able to get it to show properly but adjusting the location of the calls to turn on and off its visibility property fixed that.
Now, it seems, it loses its Windows XP style randomly. Can't explain that either. That happened to me with the "Update Section" button much earlier in my project (before ever implementing threading) but I gave up and changed it to the flat style button. Any ideas at all? I really would appreciate all of your help.
Thanks in advance,
KT
-
Apr 24th, 2004, 07:18 PM
#5
So why are you threading this?
This falls in line with what I mentioned, since you call the threaded method which fills the listview then it has to keep marshalling back to the UI thread to update the control. This will lock the control which make it seem invalidated. Why not just ditch the threading and have it fill synchronously (normal)? You could also use a callback to the main thread to make it safe multithreading.
-
Apr 24th, 2004, 07:45 PM
#6
Thread Starter
Lively Member
Okay, slow down, I'm not sure I understand what you're saying.
Before I threaded this application, I couldn't minimize it or move the window while it was running the UpdateTable or UpdateView routines. Additionally, before the threading code, the progress bar worked fine but label1 (which shows which section is being updated as called by the For Each loop in the SectionLister.List function) was not being refreshed every time a new section was parsed. It would not show anything, period. Threading the application made it more responsive while the updates were occuring.
Additionally, what you're saying about the progress bar doesn't make any sense. At first I thought it was being invalidated, but after changing the design-time visibility property to true and calling visibility = false on the Form Load subroutine, that fixed the issues I was having with it losing its XP style function, which I think is very, very strange. However, it works, and it looks good.
I'd still like to find out why it was doing that, but that's another issue. Now, why is it that my Outlook style bar gets invalidated when I don't have any references to it in a new thread? That's my question. What is wrong with my threading code? I don't need a callback for the progress bar, this happened before I even implemented the progress bar.
And if you can't help me with that, at least maybe we can figure out why the progress bar would sometimes lose its XP style when the design-time visibility property was set to false.
-
Apr 24th, 2004, 08:14 PM
#7
This is only guessing but I think the Outlook bar seems to be invalidating because of lag - Actually first a question, can you move the form around while the listview is being updated and while the Ooutlook bar appears invalidated?
I'm not saying anything is 'wrong' with the threading code just that it is going to have to marshal back and forth between the background thread and the UI thread everytime it updates the ListView. This cause more work and a slow down for the threading.
-
Apr 24th, 2004, 08:28 PM
#8
Thread Starter
Lively Member
If it's not too much trouble, could I post the project and have you take a look at it? I just found another anomoly, disabling the updateButton after a click on the C1Commands instead of the UpdateTable subroutine as I have it above makes the progress bar invisible. I don't understand it at all. I changed it back and it fixed it, only using Undo would do it, changing the code back manually did not do it. Am I finding bugs in VS.NET?
Let me know if I can post it real quick, it's a half a meg compressed.
Thanks,
KT
-
Apr 24th, 2004, 10:02 PM
#9
Sure go ahead and post it. If it doesn't fit on the forums then you can email it [email protected]
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
|