3

Possible Duplicate:
C# Splash Screen Problem

I am new to c# , i am working on splash screen which runs when the software starts.. I have a function in splash Screen class which checks the database. I am using thread to call the function

        sc = new splashScreen();

        checkDLLThread = new Thread(new ThreadStart(sc.checkDLLS).BeginInvoke);
        checkDLLThread.Start();

        while (checkDLLThread.IsAlive)
        {
            Thread.Sleep(200);
        }

Problem is UI is blocked until the thread is Alive. And in final it give me database connection status message. Here is my code. I have used checkDLLThread.join() but it also doesnt work.

Community
  • 1
  • 1
greatmajestics
  • 1,083
  • 4
  • 19
  • 41
  • Why don't you just remove the Sleep? That is whats blocking the UI. – usr Aug 04 '12 at 10:32
  • 1
    I already tried by removing sleep , the loop then blocks the UI – greatmajestics Aug 04 '12 at 10:37
  • Well, also remove the loop of course ;-) Unblocking the UI thread requires returning from your event handler. – usr Aug 04 '12 at 10:38
  • That is the problem , i want to check wether database is initilized or not , its more then a splash screen , i am checking my database behind the scene. if the database failed to connect then a proper message will be displayed and application will exit – greatmajestics Aug 04 '12 at 10:40
  • If I may, there are some useful examples in this answer: http://stackoverflow.com/questions/48916/multi-threaded-splash-screen-in-c. There is also the http://www.codeproject.com/Articles/5454/A-Pretty-Good-Splash-Screen-in-C example here; you can show the splash screen in a new thread while your main thread gets on with the work it needs to do, and, when finished, it can signal to the splash screen to close. – dash Aug 04 '12 at 10:55

4 Answers4

1

A splashscreen is simply an image to 'amuse' the user while your app is loading. Use the app_load method to execute code on startup:

Like so: (in app.xaml and app.xaml.cs)

    <Application /some references to stuff/ Startup="Application_Startup" >

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        // your startupcode
    }

Also, I think the BackGroundworker class is better for things like this, if you don't want to bother the UI.

AmazingDreams
  • 3,136
  • 2
  • 22
  • 32
1

Unblocking the UI thread requires returning from your event handler. There is no alternative to doing that. Here is some pseudo-code:

OnStartup:
 Start new Thread
 Disable UI
 Show Splash Sceen
 Return!

Thread:
 Check Database
 if (not ok)
  Show Message box
  Exit Application
 else
  Enable UI
  Remove Splash Screen

The trick is to let the thread show the message and so one once it is done. Don't wait for the thread, let the thread do it itself.

Your thread probably needs to use the Invoke function to access the UI. You might wan't to read about that a bit because there is no way around it if you want to do asynchronous work on a background thread.

usr
  • 168,620
  • 35
  • 240
  • 369
1

The following code launches a "splash screen" on a separate thread whilst your application (in my example below it is called MainForm()) loads or initialises. Firstly in your "main()" method (in your program.cs file unless you have renamed it) you should show your splash screen. This will be a WinForm or WPF form that you wish to show the user at start up. This is launch from main() as follows:

[STAThread]
static void Main()
{
    // Splash screen, which is terminated in MainForm.       
    SplashForm.ShowSplash();

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    // Run UserCost.
    Application.Run(new MainForm());
}

In your SplashScreen code you need something like the following:

public partial class SplashForm : Form
{

    // Thredding.
    private static Thread _splashThread;
    private static SplashForm _splashForm;    

    public SplashForm()
    {
        InitializeComponent();
    }

    // Show the Splash Screen (Loading...)      
    public static void ShowSplash()    
    {        
        if (_splashThread == null)        
        {            
            // show the form in a new thread            
            _splashThread = new Thread(new ThreadStart(DoShowSplash));            
            _splashThread.IsBackground = true;            
            _splashThread.Start();        
        }    
    }    

    // Called by the thread    
    private static void DoShowSplash()    
    {        
        if (_splashForm == null)            
            _splashForm = new SplashForm();        
        // create a new message pump on this thread (started from ShowSplash)        
        Application.Run(_splashForm);
    }    

    // Close the splash (Loading...) screen    
    public static void CloseSplash()    
    {        
        // Need to call on the thread that launched this splash        
        if (_splashForm.InvokeRequired)            
            _splashForm.Invoke(new MethodInvoker(CloseSplash));        
        else            
            Application.ExitThread();    
    }

}

This launches the splash form on a separate background thread allowing you to proceed with the rendering of your main application simultaneously. To display messages about loading you will have to pull information from the main UI thread, or work in purely aesthetic nature. To finish off and close the splash screen down when your application has been initialised you place the following inside the default constructor (you could overload the constructor if you wanted to):

    public MainForm()
    {
        // ready to go, now initialise main and close the splashForm. 
        InitializeComponent();
        SplashForm.CloseSplash();
    }

The code above should be relatively easy to follow.

I hope this helps.

MoonKnight
  • 23,214
  • 40
  • 145
  • 277
1

Your approach is good, but you should run both simultaneously. A good use of static fields can do the job easily. Instead of:

    while (checkDLLThread.IsAlive)
    {
        Thread.Sleep(200);
    }

You should:

  • Show the Splash Form
  • Set the form to be hidden on start, i.e. set Opacity to 0
  • Check steadily for a variable in the SplashForm when your form is completely initialized
  • Set Opacity back to 1 when the thread is complete. i.e. variable changes

i.e.:

public Form1(){
     InitializeComponent();
     Opacity = 0;
     while(sc.IsComplete){}
     Opacity = 1;
}

And inside your SplashForm, you should have something like:

internal static bool IsComplete;

internal static void CheckDLLS()
{
    //after doing some stuff
    IsComplete = true;
}
Chibueze Opata
  • 9,856
  • 7
  • 42
  • 65