Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在方法执行代码时显示进度表单的最佳方法?_C#_Multithreading - Fatal编程技术网

C# 在方法执行代码时显示进度表单的最佳方法?

C# 在方法执行代码时显示进度表单的最佳方法?,c#,multithreading,C#,Multithreading,我有一个WinForm加载方法,它需要很长时间来收集一些数据以显示给用户 在执行此方法时,我将显示一个大字体的表单,其中包含单词“Loading” 但是,有时会出现此错误,“加载”进度表不会关闭,最终我的整个应用程序将退出: 创建窗口句柄时出错。位于System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp) 在load方法中执行代码时,是否有更好的方法显示进度/加载表单? 这是我的代码: //I launch a thread

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

在执行此方法时,我将显示一个大字体的表单,其中包含单词“Loading”

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

创建窗口句柄时出错。位于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)
{
}

我会将加载方法中的代码放入线程中。在表单上的某个位置设置进度条,并在收集数据的代码的关键阶段增加进度条-但注意不要在线程本身中这样做,即不要在单独的线程中篡改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线程完成,因为它最终必须拥有这些对象。这就是为什么有些应用程序使用闪屏,真的。