Results 1 to 9 of 9

Thread: Control invalidated on new thread start.

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Apr 2004
    Posts
    95

    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

  2. #2

    Thread Starter
    Lively Member
    Join Date
    Apr 2004
    Posts
    95
    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.

  3. #3
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    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.

  4. #4

    Thread Starter
    Lively Member
    Join Date
    Apr 2004
    Posts
    95

    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:
    1. Private Sub showGames_Click(ByVal sender As System.Object, ByVal e As C1.Win.C1Command.ClickEventArgs) Handles showGames.Click
    2.         navBar.Enabled = False
    3.         sectionSelected = 2
    4.         Label2.Text = "Games"
    5.         Dim viewThread As New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf Me.UpdateView))
    6.         viewThread.Start()

    Which calls this:

    VB Code:
    1. Private Sub UpdateView()
    2.  
    3.         If sectionSelected = 1 Then
    4.            'omitted as I'm still working on this.
    5.         ElseIf sectionSelected = 2 Then
    6.             view.ParseTable(gamesTable, ListView1, mainBar)
    7.         ElseIf sectionSelected = 3 Then
    8.             view.ParseTable(moviesTable, ListView1, mainBar)
    9.         ElseIf sectionSelected = 4 Then
    10.             view.ParseTable(showsTable, ListView1, mainBar)
    11.         ElseIf sectionSelected = 5 Then
    12.             view.ParseTable(animeTable, ListView1, mainBar)
    13.         ElseIf sectionSelected = 6 Then
    14.             view.ParseTable(musicTable, ListView1, mainBar)
    15.         ElseIf sectionSelected = 7 Then
    16.             view.ParseTable(appsTable, ListView1, mainBar)
    17.         ElseIf sectionSelected = 8 Then
    18.             view.ParseTable(comicsTable, ListView1, mainBar)
    19.         ElseIf sectionSelected = 9 Then
    20.             view.ParseTable(macTable, ListView1, mainBar)
    21.         ElseIf sectionSelected = 10 Then
    22.             view.ParseTable(miscTable, ListView1, mainBar)
    23.         End If
    24.         navBar.Enabled = True
    25.  
    26.     End Sub

    Here's the ViewManager class that contains the ParseTable sub (called by the instance "view" as shown above):

    VB Code:
    1. Public Class ViewManager
    2.  
    3.     Public Sub ParseTable(ByVal table As DataTable, ByVal list As ListView, ByVal _
    4.     progress As ProgressBar)
    5.  
    6.         list.Visible = False
    7.         list.Items.Clear()
    8.  
    9.         Dim rows As DataRowCollection
    10.         Dim row As DataRow
    11.         rows = table.Rows
    12.  
    13.         progress.Maximum = rows.Count
    14.  
    15.         For Each row In rows
    16.             Dim lvi As New ListViewItem(CType(row(1), String))
    17.  
    18.             lvi.SubItems.Add(CType(row(2), String))
    19.             lvi.SubItems.Add(CType(row(3), String))
    20.             lvi.SubItems.Add(CType(row(5), String))
    21.             lvi.SubItems.Add(CType(row(6), String))
    22.             lvi.SubItems.Add(CType(row(7), String))
    23.             lvi.SubItems.Add(CType(row(8), String))
    24.  
    25.             list.Items.Add(lvi)
    26.             progress.Value += 1
    27.  
    28.         Next row
    29.         list.Visible = True
    30.         progress.Visible = False
    31.         progress.Value = 0
    32.  
    33.     End Sub
    34.  
    35. 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:
    1. Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonUpdate.Click
    2.  
    3.         navBar.Enabled = False
    4.         mainBar.Visible = True
    5.         ListView1.Visible = False
    6.         Dim updateThread As New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf Me.updateTable))
    7.         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:
    1. Private Sub updateTable()
    2.  
    3.         buttonUpdate.Enabled = False
    4.  
    5.         If sectionSelected = 1 Then
    6.            ' again I'm still working on the newslister function as the news section is different from other sections, such as games.
    7.             newsTable = newsLister.List(newsUrl)
    8.         ElseIf sectionSelected = 2 Then
    9.             gamesTable = sectionLister.List(gamesUrl, Me.mainBar, Me.Label1)
    10.             Me.UpdateView()
    11.         ElseIf sectionSelected = 3 Then
    12.             moviesTable = sectionLister.List(moviesUrl, Me.mainBar, Me.Label1)
    13.             Me.UpdateView()
    14.         ElseIf sectionSelected = 4 Then
    15.             showsTable = sectionLister.List(showsUrl, Me.mainBar, Me.Label1)
    16.             Me.UpdateView()
    17.         ElseIf sectionSelected = 5 Then
    18.             animeTable = sectionLister.List(animeUrl, Me.mainBar, Me.Label1)
    19.             Me.UpdateView()
    20.         ElseIf sectionSelected = 6 Then
    21.             musicTable = sectionLister.List(musicUrl, Me.mainBar, Me.Label1)
    22.             Me.UpdateView()
    23.         ElseIf sectionSelected = 7 Then
    24.             appsTable = sectionLister.List(appsUrl, Me.mainBar, Me.Label1)
    25.             Me.UpdateView()
    26.         ElseIf sectionSelected = 8 Then
    27.             comicsTable = sectionLister.List(comicsUrl, Me.mainBar, Me.Label1)
    28.             Me.UpdateView()
    29.         ElseIf sectionSelected = 9 Then
    30.             macTable = sectionLister.List(macUrl, Me.mainBar, Me.Label1)
    31.             Me.UpdateView()
    32.         ElseIf sectionSelected = 10 Then
    33.             miscTable = sectionLister.List(miscUrl, Me.mainBar, Me.Label1)
    34.             Me.UpdateView()
    35.         End If
    36.  
    37.         navBar.Enabled = True
    38.         buttonUpdate.Enabled = True
    39.  
    40.     End Sub

    And finally, in case you're curious, here's the sectionLister.List function that is called above.

    VB Code:
    1. Public Class SectionLister
    2.     Dim lastEntry As Boolean = False
    3.     Dim nextEntry As Integer
    4.     Dim lastItem As Boolean = False
    5.     Dim nextItem As Integer
    6.  
    7.     Dim torrentTable As DataTable
    8.     Dim subProgress As ProgressBar
    9.     Dim subLabel As Label
    10.  
    11.  
    12.  
    13.  
    14.     Function List(ByVal sectionUrl As String, ByVal subProgress As ProgressBar, ByVal subLabel As Label) As DataTable
    15.  
    16.         torrentTable = New DataTable
    17.  
    18.         Dim _id As DataColumn = New DataColumn("ID")
    19.         _id.DataType = System.Type.GetType("System.Int32")
    20.         torrentTable.Columns.Add(_id)
    21.  
    22.         Dim _time As DataColumn = New DataColumn("Time")
    23.         _time.DataType = System.Type.GetType("System.String")
    24.         torrentTable.Columns.Add(_time)
    25.  
    26.         Dim _section As DataColumn = New DataColumn("Section")
    27.         _section.DataType = System.Type.GetType("System.String")
    28.         torrentTable.Columns.Add(_section)
    29.  
    30.         Dim _name As DataColumn = New DataColumn("Name")
    31.         _name.DataType = System.Type.GetType("System.String")
    32.         torrentTable.Columns.Add(_name)
    33.  
    34.         Dim _url As DataColumn = New DataColumn("URL")
    35.         _url.DataType = System.Type.GetType("System.String")
    36.         torrentTable.Columns.Add(_url)
    37.  
    38.         Dim _size As DataColumn = New DataColumn("Size")
    39.         _size.DataType = System.Type.GetType("System.String")
    40.         torrentTable.Columns.Add(_size)
    41.  
    42.         Dim _seeds As DataColumn = New DataColumn("Seeds")
    43.         _seeds.DataType = System.Type.GetType("System.Int32")
    44.         torrentTable.Columns.Add(_seeds)
    45.  
    46.         Dim _peers As DataColumn = New DataColumn("Peers")
    47.         _peers.DataType = System.Type.GetType("System.Int32")
    48.         torrentTable.Columns.Add(_peers)
    49.  
    50.         Dim _quality As DataColumn = New DataColumn("Quality")
    51.         _quality.DataType = System.Type.GetType("System.String")
    52.         torrentTable.Columns.Add(_quality)
    53.  
    54.         Dim _donor As DataColumn = New DataColumn("Donor")
    55.         _donor.DataType = System.Type.GetType("System.String")
    56.         torrentTable.Columns.Add(_donor)
    57.  
    58.         Dim _donorrank As DataColumn = New DataColumn("Donor Rank")
    59.         _donorrank.DataType = System.Type.GetType("System.String")
    60.         torrentTable.Columns.Add(_donorrank)
    61.  
    62.         Dim _info As DataColumn = New DataColumn("Info URL")
    63.         _info.DataType = System.Type.GetType("System.String")
    64.         torrentTable.Columns.Add(_info)
    65.  
    66.         Dim getsubs As New SubsectionLister
    67.         Dim http As New Connecter
    68.  
    69.  
    70.         Dim subsectionList As Hashtable = getsubs.List(sectionUrl)
    71.         subProgress.Maximum = subsectionList.Count
    72.  
    73.         Dim entry As DictionaryEntry
    74.  
    75.         For Each entry In subsectionList
    76.  
    77.             Dim url As String = CType(entry.Value, String)
    78.             Dim title As String = CType(entry.Key, String)
    79.             subProgress.Update()
    80.             subProgress.Value += 1
    81.             subLabel.Text = "Listing: " & title
    82.             Dim html As String = http.Download(url)
    83.             ListSingleSection(html)
    84.  
    85.         Next entry
    86.         subProgress.Value = 0
    87.         subLabel.Text = ""
    88.         Return torrentTable
    89.  
    90.     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

  5. #5
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    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.

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Apr 2004
    Posts
    95
    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.

  7. #7
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    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.

  8. #8

    Thread Starter
    Lively Member
    Join Date
    Apr 2004
    Posts
    95
    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

  9. #9
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    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
  •  



Click Here to Expand Forum to Full Width