|
Hi Martin,
I am not sure when and how Geert organized the initialization.
It may be OK, it may be sequential, depends on the code.
I cant tell when LoadData() gets called, I hope inside the form's
constructor.
As a consequence I am unsure what the handles got to do with it;
also you can enforce the handles to be generated by doing something
that needs them, not necessarily painting the form. So I dont feel
like fiddling with OnPaint.
My advise is to add logging with timestamps, so Geert has the
facts on which he can then proceed.
|
|
|
|
|
But the combobox is already being filled during the splashscreen, so the db code is handled BEFORE I even call the Show function of the form.
But, then the showing of the combobox takes a long time.
|
|
|
|
|
That's what I assumend and what Luc missunderstood (at least I think so).
I don't think that the filling of the combobox is the bottleneck, I think the painting itself takes long for the first time!
All the best,
Martin
|
|
|
|
|
Exactly!
However, I can't show the main form in the splash screen since that is handled in a separate thread (and it is giving me some (understandble and logical) dragdrop errors).
Best regards,
|
|
|
|
|
Geert van Horrik wrote: However, I can't show the main form in the splash screen since that is handled in a separate thread
If you use the ApplicationContext class, like in this article from jconwell[^], you can!
Hope it helps!
All the best,
Martin
|
|
|
|
|
Thank you
I will check out that article and implement it that way!
Thanks!
|
|
|
|
|
The problem is that I have created a SplashScreen control for our company. We simply have to derive a new class and override the HandleSplash() function and the splashscreen will perform the other data.
In the constructor I create a new thread to perform initialization, so the SplashScreen stays updated correctly. So, the ApplicationContext will not work since I still have a different thread which will create the real instance of the mainform.
Best regards,
|
|
|
|
|
Why not instanciate the mainform and all other used classes in the SplashAppContext constructor.
From there you could inform the splash and also Show the mainform.
As long as the mainform isn't automaticaly Closed (over the OnPaint, like I said before), the Splash stays TopMost opened.
All the best,
Martin
|
|
|
|
|
Hello Geert,
I just did a little test with the sampleproject of the article I was giving you!
I placed a lot of ListBoxes and ComboBoxes filled with lotts of Items on the Form1.
If you then start the proram, you can see the delay after the splash is closed bevore the Form1 is shown.
I than changed the constructor of SplashAppContext to:
public SplashAppContext(Form mainForm, Form splashForm) : base(splashForm)
{
this.mainForm = mainForm;
mainForm.Show();
splashTimer.Tick += new EventHandler(SplashTimeUp);
splashTimer.Interval = 2000;
splashTimer.Enabled = true;
}
And added OnPaint to Form1 like this:
private bool init=true;
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);
if(init)
{
init=false;
this.Hide();
}
}
After that the Form1 shown very fast.
All the best,
Martin
|
|
|
|
|
I have been researching this problem too.
It seems that filling the Items property is the one tackling down. The debugger shows this code already being executed at the InitializeComponent function, but internally, I guess the combobox lists the items when it is first shown (bad habit btw).
What I am planning now is disabling the automatic updating and showing the screen and hide it immediately. Then, I manually call a function to populate the data which I hope can be done from within the splashscreen.
Best regards,
|
|
|
|
|
Let us know if it works out for you!
Good luck
All the best,
Martin
|
|
|
|
|
Now I am facing the Thread problem since I create a worker thread in the splashscreen that does all the initializing.
I guess it's just a thing I have to live with.
I will keep investigating this and let you know any progress updates!
|
|
|
|
|
Hello,
Maybe you should think about the concept of your splash again.
In my understanding the mainthread should do the initializing (also the mainform) and give the splash the informationions for the user.
If you are showing progressbars and other GUI stuff you would have to use Application.DoEvents().
All the best,
Martin
|
|
|
|
|
Good idea.
Currently, I have managed to fix the problem by invoking a InitializeMainForm method in the thread so it is handled in the main thread again.
Then, I wait until I fire the even mainFormInitialized. This seem to work, but I will definitely try your way too!
Best regards,
|
|
|
|
|
I have now moved everything to the main thread, and all problems are fixed.
Thanks for helping me out on this one!
Best regards,
|
|
|
|
|
Glad I could help!
Geert van Horrik wrote: Thanks for helping me out on this one!
All the best,
Martin
|
|
|
|
|
Hi Geert,
Geert van Horrik wrote: But the combobox is already being filled during the splashscreen
is that what you intend to happen, or do you have actual prove of it ?
BTW: any chance your LoadData() is executed more than once, i.e. the initialization is
maybe OK, but possibly you load the data again by mistake ??
Maybe we need to see more code to actually help you...
Regards
|
|
|
|
|
I am very sure since I add a breakpoint at the ListData of the ComboBox control. It is called during the splashscreen.
When I show the form finally with:
<br />
Application.Run(MainForm.GetInstance());<br />
The breakpoint never gets called again, so I am VERY sure the combobox is already listed. The problem is probably the first time drawing the combobox...
|
|
|
|
|
OK, but drawing a ComboBox is cheap. It is like a TextBox plus a Button (for the arrow);
it is not even interested in its own data unless you click the arrow to drop it down.
So I suspect other things, see my earlier messages (lower in the thread though).
|
|
|
|
|
Hi Geert,
all Controls have SuspendLayout, some also have BeginUpdate.
I dont know what the difference is, probably nothing.
some ideas/suggestions:
- I dont know anything about DB access, but most often I see SQL statements that fill
a DataTable/DataSet, then use that data. Wouldnt that be faster than looping a reader ?
- try your stopwatch on the database stuff independent of the control; if it takes say
5 seconds, then that's what it is, whatever you optimize in the control itself.
- having the splash in the main thread and the initialization in a background thread,
although intuitive, may be the wrong way: I suspect the foreground window and thread
to get priority over the background threads. There is a very complicated scheme of
mapping the 5+1 user defined thread priorities (Normal, aboveNormal, etc, onto the
32 integer levels XP is actually dealing with, and it depends on currentProcess
and window state). Your background worker may sit behind or next to some other
thread in same or other process, your main thread would not (unless the other
thread is "aboveNormal").
Please dont interpret this as a suggestion to start using "aboveNormal" yourself.
The system behavior soon gets very ugly if you do.
Hope this helps.
PS: I typically include logging in all my apps, and each log line starts automatically
with the current time (seconds and milliseconds), so I can more easily see what
happens when, and what takes (too) long.
-- modified at 9:14 Thursday 19th July, 2007
|
|
|
|
|
Thanks for your message and taking the time to help me (same for Martin!).
First about the reader:
When you load everything into a dataset, it must load everything into memory. What I know is that the datareader is the fastest component since it is forward-only and read-only. The dataset is a complete copy of the part of the database which you can edit and update.
Now back to the real problem:
I have a combobox control which loads the db data as soon as I construct the form. So, before I even call the Show form, the combobox already has all the values listed. This process doesn't take very long (about 2 seconds) to list the data from the db and store it in the combobox items property.
However, as soon as I show the form, it takes long (and the items property doesn't get changed anymore at that moment).
That's why I am confused.
|
|
|
|
|
Hi Geert,
this sounds like a different cause all together.
How complex is your form, how many controls are there, anything trying to
setup a connection to a DB or another machine, anything special in there ?
if all is normal, reasonnable and simple:
- how is your CPU load during the wait period ? 100% ? 50 % ? less ? (do you have
a dual core, or a hyperthreading CPU ?
- any Thread.Sleep() included ?
- any cross-thread sins ?
- is it also slow without Visual ? double click the exe, if that is fast, its
because Visual needs some 5 seconds to process the first exception you get
(at least it used to be, dont know the current status on that)
- anything involving several threads with joins and/or possible resource allocation
problems (almost deadlocks) ?
if none of the above help, I see only two routes to go, take your pick:
- add logging with timestamp to a lot of things, and study that log file
- remove a lot of things and watch when it suddenly goes lots faster.
(obviously I prefer the logging methodology).
|
|
|
|
|
Hi Geert,
you got us confused now; at one time you said showing the ComboBox was slow
(I assumed then it was not dropped down, so basically showing an empty TextBox+Arrow,
and clicking it resulted in a very slow dropping down); but now you say
showing the form itself is slow.
depending on which it is, seems to me the splash screen might not be involved at all.
PS: I should have posted this message first, before the one right above it !
|
|
|
|
|
I have a procject in which i am using a custom webclient.
I have following event _WebClient.DocumentComplete which i can register and it works.
Now if I want to unregister the first event handler and assign a new event handler I gives me error because I can't use
_WebClient.DocumentComplete = null;
Can some 1 tell me how to unregister the event
o O º(`'·.,(`'·., ☆,.·''),.·'')º O o°
»·'"`»* *☆ t4ure4n ☆* *«·'"`«
°o O º(,.·''(,.·'' ☆`'·.,)`'·.,)º O o°
|
|
|
|
|
When you add an event handler you use +=
to remove one you use -=
_WebClient.DocumentComplete -= new EventHandler(yourEventHandlerNameHere);
Hope that helps.
Ben
|
|
|
|