|
-
Jun 12th, 2012, 09:18 PM
#1
[RESOLVED] Load form but don't display it
I have an app where there's an edit form and it loads a bunch of stuff into comboboxes which takes half a minute to load the first time. Once it's loaded I keep the instance of the form and just hide it instead of disposing it until the app exits. What I would like to do is in the Sub Main of the app (there is no startup form) I would like to launch a new thread and load that form into memory, but I don't want the form to be displayed at that time, what's the best way to do this?
-
Jun 12th, 2012, 09:57 PM
#2
Re: Load form but don't display it
Do you really need to load the form? I'm guessing that the slow step is getting all the data, not the displaying of that data in the form. Can you not just load the data into a cache at startup? That would then also allow you to dispose your form instead of hiding.
-
Jun 13th, 2012, 10:19 AM
#3
Re: Load form but don't display it
Right now the app launches a thread as one of the first steps, in the thread it goes and loads eveything into a couple of lists (List(Of T)), then when this "Edit" form is loaded it puts the contents of those lists into a few ComboBox's and stuff like that, so even though all of the data is loaded into lists, it still takes the form 20 to 30 seconds to load that edit form. When the form loads that first time the Lists are destroyed and I hang on to that built form for future use, which only takes it a second or two to be ready to display to the user after it's been shown once.
What I would like to do is in the thread that builds those Lists is instead of building the lists, it goes and builds the entire edit form so on the first showing it only takes a second or two instead of half a minute.
-
Jun 13th, 2012, 06:57 PM
#4
Re: Load form but don't display it
You can't "build the form" on a secondary thread and then display out on the UI thread.
20 - 30 seconds to simply bind some lists to some ComboBoxes sounds excessive. How many lists and how many items per list are we talking about? Are you maybe adding the items directly in a loop instead of binding?
-
Jun 14th, 2012, 01:19 AM
#5
Re: Load form but don't display it
 Originally Posted by JuggaloBrotha
What I would like to do is in the thread that builds those Lists is instead of building the lists, it goes and builds the entire edit form so on the first showing it only takes a second or two instead of half a minute.
Like jmc says, you can't but I would say shouldn't. I've seen some really odd and ugly behaviour when forms are created on any thread other than the UI thread. However, you could create your form on the UI thread and just invoke from your other thread to fill out the data while the form is hidden.
-
Jun 15th, 2012, 08:34 AM
#6
Re: [RESOLVED] Load form but don't display it
Pity, I was hoping to be able to do it, but I'll just leave it as is and that initial load time is something I'll have have to live with.
-
Jun 15th, 2012, 09:25 AM
#7
Re: [RESOLVED] Load form but don't display it
Your load time is surely caused by the ComboBox:-
vbnet Code:
' Dim lst As New List(Of String) For i = 1 To 100000 ComboBox1.Items.Add("Item " + CStr(i)) 'lst.Add("Item " + CStr(i)) Next MsgBox("Done")
The code above takes 11 full seconds when adding to the ComboBox. Wanna guess how long it takes to add to the list ?........Less than 1 second!!! Its practically instant.
-
Jun 15th, 2012, 11:05 PM
#8
Re: [RESOLVED] Load form but don't display it
You seem to be giving up a bit easily JB. As Niya suggests, I reckon the issue is how you are populating the controls. I did ask a couple of questions in post #4 that have gone unanswered. If you are adding items to the ComboBoxes directly in a one-by-one fashion then that is almost certainly the issue. You should certainly either binding or calling AddRange.
-
Jun 17th, 2012, 01:48 AM
#9
Re: [RESOLVED] Load form but don't display it
I've tried AddRange as well but still it suffers. Upon look at the code for AddRange I see it calls Add anyway so its not really different from adding items one at a time. One peculiar thing is that it adds all the items instantly when the control isn't sited. That is to say, if you instantiate a ComboBox control in code and add the items before adding it to a container, the items are all added in less than a second. When I saw this, I thought 'Ah ha I got it!" but upon adding to a Form's control collection to site it, it halted for 11 seconds. My conclusion is that there is something that it has to do with the items before the ComboBox is to be displayed. There is simply no way around it as far as I can tell. Suspending the layout doesn't work. I haven't tried turning it invisible but I suspect it would just halt to process the items when it does become visible again.
I think using a background thread to add the items while the control is sited is the only simple solution. Writing your own ComboBox would be the ideal solution but its no trivial matter.
-
Jun 17th, 2012, 02:11 AM
#10
Re: [RESOLVED] Load form but don't display it
 Originally Posted by Niya
I've tried AddRange as well but still it suffers. Upon look at the code for AddRange I see it calls Add anyway so its not really different from adding items one at a time.
The difference is that AddRange calls BeginUpdate before adding the items and then EndUpdate after adding them. You could do that yourself if you wanted to but, given that AddRange already does it, there's no point.
 Originally Posted by Niya
I think using a background thread to add the items while the control is sited is the only simple solution. Writing your own ComboBox would be the ideal solution but its no trivial matter.
That's going to throw a cross-threading exception while debugging unless you set CheckForIllegalCrossThreadCalls to False but not checking for them still doesn't guarantee that they'll succeed.
FYI, I just tested this code:
Code:
Public Class Form1
Private items As String() = Enumerable.Range(1, 100000).Select(Function(n) "Hello World").ToArray()
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim timer = Stopwatch.StartNew()
For Each item In items
ComboBox1.Items.Add(item)
Next
MessageBox.Show(timer.Elapsed.ToString())
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim timer = Stopwatch.StartNew()
ComboBox1.BeginUpdate()
For Each item In items
ComboBox1.Items.Add(item)
Next
ComboBox1.EndUpdate()
MessageBox.Show(timer.Elapsed.ToString())
End Sub
Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
Dim timer = Stopwatch.StartNew()
ComboBox1.Items.AddRange(items)
MessageBox.Show(timer.Elapsed.ToString())
End Sub
Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
Dim timer = Stopwatch.StartNew()
ComboBox1.DataSource = items
MessageBox.Show(timer.Elapsed.ToString())
End Sub
End Class
I tested each Button twice, closing and re-opening the application each time. Button1 took between 10 and 12 seconds. Button2 took between 2.5 and 3 seconds. Button3 took about 2.5 seconds each time. Button4 took about 3.3 seconds each time. Clearly, AddRange and data-binding are about 4 times faster than adding items one by one without calling BeginUpdate and EngUpdate.
-
Jun 17th, 2012, 02:38 AM
#11
Re: [RESOLVED] Load form but don't display it
 Originally Posted by jmcilhinney
That's going to throw a cross-threading exception while debugging unless you set CheckForIllegalCrossThreadCalls to False but not checking for them still doesn't guarantee that they'll succeed.
Gimme some credit, you should know I know better than to do something blasphemous like that . I meant to do it properly. Load the form and have a background thread add the items by using the whole InvokeRequired/Invoke pattern so the ComboBox's operation doesn't lock up the UI. I actually did this is the past with something like 10000 items complete with a progress bar.
As for your tests. The results are interesting. I didn't compare the different methods against each other but against a List<T>. The List<T> was practically instant and I was aiming for that level of performance. Granted, 3 seconds is a whole lot better than 10 but locking up the UI for even 2 seconds is very annoying. As a user, I hate when any application I'm using does this, it gives the app a sluggish feel, and as a programmer I try to avoid inflicting it on users.
Last edited by Niya; Jun 17th, 2012 at 02:41 AM.
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
|