1

我遇到了一些我无法自行解决的奇怪问题...我使用线程创建了启动画面(Form3 ~ SplashScreen),不知何故在应用程序到达该部分之后

线程.Abort();

(实际上会杀死线程)启动画面会一直留在屏幕上,直到我将鼠标移到它上面,或者在其他表单(例如 Form1)的某个地方单击它...我变得更加困惑,因为这在 VS 中不会发生当我运行应用程序时。启动画面正在正确关闭......,它只发生在编译的 .exe Program.cs 上

     namespace ICAMReports
 {
     static class Program
    {

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

闪屏.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....
    }
}

任何线索,为什么会发生这种情况或如何解决这个问题?

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

4

1 回答 1

1

MSDN 说关于 thread.Abort,“调用这个方法通常会终止线程。”

有无数种方法可以在不使用 thread.Abort 的情况下关闭启动画面。

这是完成您正在尝试做的事情的一种方法。

闪屏.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();
        } } } }

表格1.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() 将完成您尝试使用 Sleep() 执行的相同操作,但您应该使用启动画面中的加载栏来告诉您何时结束线程。实际上,在这种情况下,将启动画面放在单独的线程上确实没有任何意义,因为睡眠/等待会暂停主窗体加载任何内容,直到启动画面完成。假设您的 Form1 中有资源密集型的东西,您想在启动画面分散用户注意力时加载这些东西。您会做这样的事情,而不是完全暂停 Form1(因为使用单独线程的全部意义在于它们都同时运行。

闪屏.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();
        } } } }

表格1.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....
    }
    }

编辑:响应加载条动画

根据您使用的 Windows 版本和设置,加载栏会移动并且看起来会有所不同。您不能使用 Thread.Sleep 让加载条赶上,因为它会暂停 loadingBar1 动画。你需要给你的加载栏大约 10% 来赶上(根据需要调整它)这应该可以解决你的加载栏动画问题。

    int i = 0;
    private void timer1_Tick(object sender, EventArgs e)
    {
        if(i++<100)progressBar1.Value++;
        if (i == 110)
        {
         splashDone.Set();
         this.Close();
        }
    }
于 2013-06-03T12:06:01.907 回答