在方法执行代码时显示进度表单的最佳方法是什么?

我有一个WinForm加载方法,需要很长时间来收集一些数据显示给用户。

在执行此方法时,我会显示一个带有大字体的表单,并带有“正在加载”字样。

但是,有时会出现此错误,并且“加载”进度表单不会关闭,然后最终我的整个应用程序将退出:

创建窗口句柄时出错。 在System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)

在我在load方法中执行代码时,是否有更好的方法来显示我的进度/加载表单?

这是我的代码:

//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) { } 

BackgroundWorker是一种在不锁定UI线程的情况下执行长时间运行操作的好方法。

使用以下代码启动BackgroundWorker并显示加载表单。

 // Configure a BackgroundWorker to perform your long running operation. BackgroundWorker bg = new BackgroundWorker() bg.DoWork += new DoWorkEventHandler(bg_DoWork); bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted); // Start the worker. bg.RunWorkerAsync(); // Display the loading form. loadingForm = new loadingForm(); loadingForm.ShowDialog(); 

这将导致在后台线程上执行以下方法。 请注意,您无法从此线程操纵UI。 试图这样做会导致例外。

 private void bg_DoWork(object sender, DoWorkEventArgs e) { // Perform your long running operation here. // If you need to pass results on to the next // stage you can do so by assigning a value // to e.Result. } 

当长时间运行的操作完成时,将在UI线程上调用此方法。 您现在可以安全地更新任何UI控件。 在您的示例中,您需要关闭加载表单。

 private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // Retrieve the result pass from bg_DoWork() if any. // Note, you may need to cast it to the desired data type. object result = e.Result; // Close the loading form. loadingForm.Close(); // Update any other UI controls that may need to be updated. } 

我会把你在load方法中的代码放到一个线程中。 在表单的某处设置一个进度条,并在收集数据的代码的关键阶段递增它 – 注意不要在线程本身中这样做,即不要在单独的线程中篡改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"); }