5

Please have a look at the following code:

var splashForm = new SplashForm();
m_Thread = new Thread( () => System.Windows.Forms.Application.Run( splashForm ) )
m_Thread.Start();

// Do some initialization
// ...

// the following method just invokes `Close()` on the right thread
splashForm.Shutdown();

// Loop until the thread is no longer alive
// ...

System.Windows.Forms.Application.Run( mainForm );

It looks as if all works fine: first I see the splashscreen, later the mainform gets started. But somehow I get strange errors, like: graphical elements (a endless ProgressBar) are not showing up correctly.
EDIT: I have two progressbars, one on the splashscreen, on on the mainform. They both show the same (wrong) behaviour in endlessmode: no progress, just the pure background./EDIT
In my opinion this is due to the call of Application.Run() on different threads. This errors can be eliminated by calling any function/property of the mainForm before starting the splashscreen - like, for instance

mainForm.Text = mainForm.Text;

Can anyone please confirm that this code can cause problems - or that it should behave alright and I have to look for the error somewhere else?
I already looked for splashscreen implementations and I know that it can be done differently. But I am interested in understanding this implementation and its possible problems. Thanks!

tanascius
  • 53,078
  • 22
  • 114
  • 136

4 Answers4

4

The thread on which your SplashForm displays needs to have a Windows message pump in order to process messages that each window/control produces consumes. To do that you need to make the thread an STA thread. Try calling SetApartmentState before starting the thread

Kevin Jones
  • 2,369
  • 16
  • 26
  • I set the ApartmentState by using m_Thread.TrySetApartmentState( ApartmentState.STA ); Unfortunately it does not help. – tanascius Aug 03 '09 at 15:48
  • This is the best I could find with a short search: http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx – Kevin Jones Aug 03 '09 at 19:17
3

I would create the form on the thread where the Application.Run() executes.

SplashForm splashForm = null;
m_Thread = new Thread(delegate { splashForm = new SplashForm(); System.Windows.Forms.Application.Run(splashForm); });
m_Thread.Start();

But what really needs to be done is access it via the InvokeRequired and BeginInvoke technique. Check here.

Kenan E. K.
  • 13,955
  • 3
  • 43
  • 48
  • Well, that's only half of it. The main part is actually the InvokeRequired part as the linked article suggests. – Kenan E. K. Aug 03 '09 at 15:34
  • I use RevokeInquired already ... that is the reason why I have the Shutdown() - it invokes just the Close()-method. – tanascius Aug 03 '09 at 15:44
2

OMG, I found the answer:
Application.EnableVisualStyles(); was called in the ctor if my mainForm (WHY?). It has to be called before any controls are created. Moving it to the static Main() did the trick. The visual styles are required for endless (ProgressBarStyle.Marquee) progressbars.
Now this splashscreen solution works as it should.

tanascius
  • 53,078
  • 22
  • 114
  • 136
  • this might have worked for you. But, I would have done it a bit differently. I assume you want to show the splashscreen only during loading. Then why create a message pump for the thread on which splash screen is created. Instead just call it on a separate thread by calling Show and when you are done, just call close. Now, create message pump by calling Application.Run(mainForm) – P.K Aug 03 '09 at 16:51
  • Yes, you might be right. The additonal call to Application.Run() can be probably skipped, I'll check this. – tanascius Aug 03 '09 at 17:17
1

There is nothing principally wrong with what you are doing. I found the approach interesting enough to whip up a demo, and it works fine. I can also say that kek444's answer isn't the problem. Creating the SplahForm on the main thread made no difference.

So I'm guessing it is in the way you control the Progressbar, or more generally how you communicate between the 2 threads.

H H
  • 263,252
  • 30
  • 330
  • 514
  • There is a progressbar on the splashscreen - in continuous mode it does not show any progress (just the background). Later in the mainform there is a progressbar, too, which shows the same behaviour in endless mode: nothing ... – tanascius Aug 03 '09 at 15:45
  • I am running a PBar on a timer - no problem. How do you push new Values? – H H Aug 03 '09 at 15:53
  • I am not pushing values - I just set the style to ProgressBarStyle.Marquee. – tanascius Aug 03 '09 at 16:25
  • I found out what the problem was - I am very sorry, since you even wrote a demo ... :/ please see my answer. – tanascius Aug 03 '09 at 16:26