C# 在方法执行代码时显示进度表单的最佳方法?
我有一个WinForm加载方法,它需要很长时间来收集一些数据以显示给用户 在执行此方法时,我将显示一个大字体的表单,其中包含单词“Loading” 但是,有时会出现此错误,“加载”进度表不会关闭,最终我的整个应用程序将退出: 创建窗口句柄时出错。位于System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp) 在load方法中执行代码时,是否有更好的方法显示进度/加载表单?C# 在方法执行代码时显示进度表单的最佳方法?,c#,multithreading,C#,Multithreading,我有一个WinForm加载方法,它需要很长时间来收集一些数据以显示给用户 在执行此方法时,我将显示一个大字体的表单,其中包含单词“Loading” 但是,有时会出现此错误,“加载”进度表不会关闭,最终我的整个应用程序将退出: 创建窗口句柄时出错。位于System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp) 在load方法中执行代码时,是否有更好的方法显示进度/加载表单? 这是我的代码: //I launch a thread
这是我的代码:
//I launch a thread here so that way the Progress_form will display to the user
//while the Load method is still executing code. I can not use .ShowDialog here
//or it will block.
//Progress_form displays the "Loading" form
Thread t = new Thread(new ThreadStart(Progress_form));
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.IsBackground = true;
t.Start();
//This is where all the code is that gets the data from the database. This could
//take upwards of 20+ seconds.
//Now I want to close the form because I am at the end of the Load Method
try
{
//abort the Progress_form thread (close the form)
t.Abort();
//t.Interrupt();
}
catch (Exception)
{
}
我会将加载方法中的代码放入线程中。在表单上的某个位置设置进度条,并在收集数据的代码的关键阶段增加进度条-但注意不要在线程本身中这样做,即不要在单独的线程中篡改ui元素,您需要使用委托调用它们。a是执行长时间运行的操作而不锁定UI线程的好方法 使用以下代码启动BackgroundWorker并显示加载表单
//配置BackgroundWorker以执行长时间运行的操作。
BackgroundWorker bg=新的BackgroundWorker()
bg.DoWork+=新DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(bg\u RunWorkerCompleted);
//启动工人。
bg.RunWorkerAsync();
//显示加载表单。
loadingForm=新的loadingForm();
loadingForm.ShowDialog();
这将导致在后台线程上执行以下方法。请注意,您无法从此线程操作UI。尝试这样做将导致异常
private void bg_DoWork(对象发送方,DoWorkEventArgs e)
{
//在此处执行长时间运行操作。
//如果您需要将结果传递给下一个
//阶段,您可以通过指定值来执行此操作
//结果。
}
当长时间运行的操作完成时,将在UI线程上调用此方法。您现在可以安全地更新任何UI控件。在您的示例中,您可能希望关闭加载表单
private void bg\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
//从bg_DoWork()检索结果过程(如果有)。
//注意,您可能需要将其转换为所需的数据类型。
对象结果=e.结果;
//关闭装货单。
loadingForm.Close();
//更新可能需要更新的任何其他UI控件。
}
我在.NET 4.0上成功地测试了它。(WinForms)我有理由相信,这将在.NET 4.0+上运行,并且应该是一个有用的代码片段,可以在流程结束时需要关闭表单的大多数项目中重用
private void SomeFormObject_Click(object sender, EventArgs e)
{
myWait = new YourProgressForm();//YourProgressForm is a WinForm Object
myProcess = new Thread(doStuffOnThread);
myProcess.Start();
myWait.ShowDialog(this);
}
private void doStuffOnThread()
{
try
{
//....
//What ever process you want to do here ....
//....
if (myWait.InvokeRequired) {
myWait.BeginInvoke( (MethodInvoker) delegate() { closeWaitForm(); } );
}
else
{
myWait.Close();//Fault tolerance this code should never be executed
}
}
catch(Exception ex) {
string exc = ex.Message;//Fault tolerance this code should never be executed
}
}
private void closeWaitForm() {
myWait.Close();
MessageBox.Show("Your Process Is Complete");
}
也许这里有一些想法:你应该用另一种方式。在后台线程中执行加载作业,并使用主UI线程显示某种进度条。@VaibhavDesai-如果耗时的操作涉及加载密集型UI对象,则有时在加载处理程序中不可能执行此操作。在这种情况下,它必须由UI线程完成,因为它最终必须拥有这些对象。这就是为什么有些应用程序使用闪屏,真的。