4

I've developed an application where I am using windows form as splash screen. After displaying splash screen, I've created a new thread to trigger new form. Now I want to close splash screen just after my form has been displayed.

I've googled my query, many discussions but couldn't find what I want.

Please guide me a little.

Thanks.

Muhammad Ali Dildar
  • 1,467
  • 6
  • 24
  • 35

5 Answers5

3

As long as you have some reference to the first form you call the Close() method on the other form. So when you create the second form give it a reference to the splash screen. Then attach a handler to the Shown event and call close on the splash screen.

In order to get around the cross thread problem you will need to create a method called something like ThreadSafeClose and define that as below. Then call that method instead of .Close()

public void ThreadSafeClose() {
        if(this.InvokeRequired) {
            this.Invoke(new MethodInvoker(this.Close));
        }
    }
kmcc049
  • 2,783
  • 17
  • 13
  • 2
    The forms are on different threads. You cannot just call a method of a control from another thread. You need to run the Close() from spash's thread using Invoke(). – Adi Sep 10 '11 at 22:11
3

In order to close the form you need to have a link to this form. The easiest way to do so is to add a new property to the Program object in your program that is static and available everywhere. Just modify your Program.cs file to make the Program class public and to add the appropriate reference:

public static class Program
{
    ///This is your splash screen
    public static Form1 MySplashScreen = new Form1();

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        /// This is how you run your main form
        Application.Run(MySplashScreen);
    }
}

Then in your form you can easily close your splash screen form using the following syntax:

Program.MySplashScreen.Close();

EDIT: In WinForms there is only one GUI thread, so as long as you perform the closing from within another form it should be safe. Should you want to close the form from a working thread spawned from a GUI, use the following code (this should reference your second form then):

this.Invoke((MethodInvoker)delegate {
            Program.MySplashScreen.Close();
});
TMB
  • 4,683
  • 4
  • 25
  • 44
Alexander Galkin
  • 12,086
  • 12
  • 63
  • 115
1

Normally you don't need a new thread. But once you have it, you can do it by sharing a bool value (name it closeSplash) between the two threads.

Put a timer on the splash form to check the value of closeSplash each second. When closeSplash is true, just call the Close() method of the Splash form.

See this if you choose to close the splash from another thread.

Community
  • 1
  • 1
Adi
  • 5,113
  • 6
  • 46
  • 59
  • @Muhammad Ali Dildar How did you solve it? Did any answer provide the solution? If so, please mark that answer as solution. – Adi Sep 12 '11 at 05:41
0

I have a hacky method i use .. may not be the best thing to do though. in the splash screen form declare a static instance of itself.

public static SplashForm splashInstance;

Then in the constructor for the splashform you can assign a value of "this".

SplashForm.splashInstance = this;

You can now call SplashForm.splashInstance.Close() from anywhere within your app.

scartag
  • 17,548
  • 3
  • 48
  • 52
  • Caution: directly calling Close() from another thread is invalid. You need to switch to the splash's form thread context to run the code. – Adi Sep 10 '11 at 22:17
  • @Muhammad Ali Dildar Please see my answer above, there is a link to a thead that may help. I personally try to avoid sending UI messages from one thread to another. Instead, try to use some shared members/properties to signal to the other thread that you want some action to be done by the UI. – Adi Sep 10 '11 at 22:38
0

You do not need a separate thread just to display a "splash screen" in a period of time. In fact, there are better ways you could design your classes to make doing this a whole lot easier to accomplish. Not using a timer here or using separate threads for this is not the proper solution IMHO. I suggest you try doing something like this:

public class SplashScreen : Form
{
    // add a timer to your form with desired interval to show

    protected override void OnShown(EventArgs e)
    {
        displayTimer.Start();
        base.OnShown(e);
    }

    private void displayTimer_Tick(object sender, EventArgs e)
    {
        this.Close();
    }
}

public class MainForm : Form
{
    protected override void OnLoad(EventArgs e)
    {
        // splash screen will be shown before your main form tries to show itself
        using (var splash = new SplashScreen())
            splash.ShowDialog();
        base.OnLoad(e);
    }
}
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272