简体   繁体   中英

splashscreen not closing properly

I'm having some strange problem which I cannot resolve by my self... I have created splash screen (Form3 ~ SplashScreen) using thread, somehow after the application gets to the part

thread.Abort();

(which actually kills the thread) splash screen stays on the screen until I move mouse on it, or click it somewhere on other form (for instance Form1)... I'm becoming more confused because, this doesn't happen in VS when I run application. The the splash screen is closing properly..., it only happens on the compiled .exe Program.cs

     namespace ICAMReports
 {
     static class Program
    {

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
 }

SplashScreen.cs

    namespace ICAMReports
{
    public partial class SplashScreen : Form
    {
        public SplashScreen()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            progressBar1.Increment(1);
            if (progressBar1.Value == 100)
            {
                timer1.Stop();
            }
        }
    }
}

Form1.cs

    namespace ICAMReports
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Thread th = new Thread(new ThreadStart(splashScreen));
            th.Start();
            Thread.Sleep(3000);
            th.Abort();
        }
        public void splashScreen()
        {
            Application.Run(new SplashScreen());
        }
       //this where the rest of code is placed....
    }
}

Any clue, why is this happening or how to fix this?

screenshot: 加载Form1后启动画面未关闭...

MSDN says concerning thread.Abort, "Calling this method usually terminates the thread."

There is a countless number of ways you can close out your Splash Screen without using thread.Abort.

Here is one such way to accomplish what it appears you are trying to do.

SplashScreen.cs

    namespace ICAMReports
{
public partial class SplashScreen : Form
{
    ManualResetEventSlim splashDone;
    public SplashScreen(ManualResetEventSlim SplashDone)
    {
     splashDone=SplashDone;
        InitializeComponent();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        progressBar1.Increment(1);
        if (progressBar1.Value == 100)
        {
            splashDone.Set();
            this.Close();
        } } } }

Form1.CS

      namespace ICAMReports
{
public partial class Form1 : Form
{
    ManualResetEventSlim splashDone = new ManualResetEventSlim(false);
    public Form1()
    {
        InitializeComponent();
        Thread th = new Thread(new ThreadStart(splashScreen));
        th.Start();
        splashDone.Wait();
    }
    public void splashScreen()
    {
        Application.Run(new SplashScreen(splashDone));
    }
   //this where the rest of code is placed....
    }
    }

splashDone.Wait() will accomplish the same thing you were trying to do with the Sleep() but instead you should use your loading Bar in your Splash Screen to tell you when to end the thread. Actually in this scenario it really doesn't make any sense to have the splash Screen on a separate thread because the sleep/wait will pause the main form from loading anything until the Splash Screen is finished. Suppose you had resource intensive things in your Form1 that you wanted to load while the Splash Screen is distracting the user. You would do something like this instead of just pausing the Form1 entirely(since the entire point of using a separate thread is that they both run simultaneously.

SplashScreen.cs

    namespace ICAMReports
{
public partial class SplashScreen : Form
{
    Form parent;
    delegate void show();
    public SplashScreen(Form Parent)
    {
     parent=Parent;
        InitializeComponent();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        progressBar1.Increment(1);
        if (progressBar1.Value == 100)
        {
            parent.Invoke(new show(()=>{parent.Opacity=100;}));
            this.Close();
        } } } }

Form1.CS

      namespace ICAMReports
{
public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
        Thread th = new Thread(new ThreadStart(splashScreen));
        th.Start();
        this.Opacity=0;
    }
    public void splashScreen()
    {
        Application.Run(new SplashScreen(this));
    }
   //this where the rest of code is placed....
    }
    }

edit: Responding to loading bar animation

The loading bar will move and look different depending on the version and settings of Windows you are using. You can't use a Thread.Sleep to let the loading bar catch up because it pauses the loadingBar1 animation. You need to give your loading bar about ~10% to catch up(adjust it as needed) this should fix your problem of the loading bar animation.

    int i = 0;
    private void timer1_Tick(object sender, EventArgs e)
    {
        if(i++<100)progressBar1.Value++;
        if (i == 110)
        {
         splashDone.Set();
         this.Close();
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM