C# 防溅屏未正确关闭
我有一些奇怪的问题,我自己无法解决。。。我已经用线程创建了闪屏(Form3~SplashScreen),在应用程序到达零件后 thread.Abort() (这实际上会终止线程)启动屏幕一直保持在屏幕上,直到我在上面移动鼠标,或者在其他窗体的某个位置单击它(例如Form1)。。。我越来越困惑,因为当我运行应用程序时,这不会发生在VS中。启动屏幕正在正确关闭…,它只发生在已编译的.exe上 Program.csC# 防溅屏未正确关闭,c#,multithreading,screen,splash-screen,C#,Multithreading,Screen,Splash Screen,我有一些奇怪的问题,我自己无法解决。。。我已经用线程创建了闪屏(Form3~SplashScreen),在应用程序到达零件后 thread.Abort() (这实际上会终止线程)启动屏幕一直保持在屏幕上,直到我在上面移动鼠标,或者在其他窗体的某个位置单击它(例如Form1)。。。我越来越困惑,因为当我运行应用程序时,这不会发生在VS中。启动屏幕正在正确关闭…,它只发生在已编译的.exe上 Program.cs namespace ICAMReports { static c
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();
}
}
}
}
表格1.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....
}
}
任何线索,为什么会发生这种情况,或者如何解决
屏幕截图:MSDN说的是关于线程的。中止,“调用此方法通常会终止线程。” 有无数种方法可以在不使用thread.Abort的情况下关闭初始屏幕 这里有一个这样的方法来完成你看起来想要做的事情 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();
} } } }
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
{
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....
}
}
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....
}
}
splashDone.Wait()将完成与Sleep()相同的操作,但是您应该使用启动屏幕中的加载栏来告诉您何时结束线程。实际上,在这个场景中,将启动屏幕放在单独的线程上是没有任何意义的,因为sleep/wait将暂停主窗体加载任何内容,直到启动屏幕完成。假设您的Form1中有资源密集型的内容,您希望在启动屏幕分散用户注意力时加载这些内容。您可以这样做,而不只是完全暂停Form1(因为使用单独线程的关键是它们同时运行)
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();
} } } }
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
{
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....
}
}
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....
}
}
编辑:响应加载条动画
加载栏会移动,并且看起来会有所不同,具体取决于您使用的窗口的版本和设置。您不能使用线程。睡眠可以让加载栏跟上,因为它会暂停加载栏1动画。您需要给加载栏大约10%的时间才能跟上(根据需要调整)这将解决加载条动画的问题
int i = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if(i++<100)progressBar1.Value++;
if (i == 110)
{
splashDone.Set();
this.Close();
}
}
inti=0;
私有无效计时器1_刻度(对象发送方,事件参数e)
{
如果(i++MSDN说与thread.Abort有关,“调用此方法通常会终止线程。”
有无数种方法可以在不使用thread.Abort的情况下关闭初始屏幕
这里有一个这样的方法来完成你看起来想要做的事情
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();
} } } }
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
{
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....
}
}
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....
}
}
splashDone.Wait()将完成与Sleep()相同的任务但是,您应该在启动屏幕中使用加载栏来告诉您何时结束线程。实际上,在这种情况下,将启动屏幕放在单独的线程上是没有任何意义的,因为睡眠/等待将暂停主窗体加载任何内容,直到启动屏幕完成当启动屏幕分散用户注意力时,在Form1中加载您想加载的内容。您可以这样做,而不是完全暂停Form1(因为使用单独线程的全部目的是它们同时运行)
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();
} } } }
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
{
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....
}
}
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....
}
}
编辑:响应加载条动画
加载栏会移动,并且看起来会有所不同,具体取决于您使用的窗口的版本和设置。您不能使用线程。睡眠可以让加载栏跟上,因为它会暂停加载栏1动画。您需要给加载栏大约10%的时间才能跟上(根据需要调整)这将解决加载条动画的问题
int i = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if(i++<100)progressBar1.Value++;
if (i == 110)
{
splashDone.Set();
this.Close();
}
}
inti=0;
私有无效计时器1_刻度(对象发送方,事件参数e)
{
如果(i++,我不知道如何在同一个问题thread中使用thread.Abort
和“正确关闭”thread.Abort实际上是th.Abort();在我理解的形式1.cs中;thread.Sleep(3000);->停止当前线程,th.Abort();->终止线程(因此关闭SplashScreen表单…)如果我错了,请纠正我…线程睡眠使线程处于睡眠状态,然后线程中止可能会关闭窗体,但它的操作不自然Yok,但是如果它关闭窗体,为什么启动屏幕仍在屏幕上…,直到:(我按键盘上的键或单击启动屏幕或其他窗体),它看起来仍然在内存中…(请参考我上传的图片)我不知道如何在同一个问题线程中使用线程。Abort
和“正确关闭”。Abort实际上是th.Abort();在我理解的形式1.csthread.Sleep(3000);->停止当前线程,而th.Abort();->终止线程(因此关闭SplashScreen窗体…)如果我错了,请更正我…线程睡眠会使线程睡眠,然后线程中止可能会关闭窗体,但其操作不自然Yok,但如果它关闭窗体,为什么启动屏幕仍在屏幕上…,直到:(我按键盘上的键或点击启动屏幕或其他表单),它看起来仍然在内存中…(请参阅我上传的图片)第一个代码工作,它修复了关闭启动屏幕(表单),但由于某些原因,progressbar1没有变为100,它以大约75%的速度关闭窗体…您需要让计时器再运行几次,以允许动画完成更新。我编辑了上面的文章,为您提供了一个可能的解决方案。只需创建一个单独的变量,该变量可以超过最大progressbar1值,并在该值等于1时退出10或任何你想要确保加载条动画完成的时间间隔。我测试了上面的110设置,它给了动画足够的时间完成。如果你需要它持续更长的时间,增加数字,如果你想让它快一点105只是勉强完成。谢谢codecamp,尽管我不了解