C#线程仍然使UI无响应

时间:2016-10-25 07:36:28

标签: c# multithreading winforms

好吧,我有一个带有按钮的form1,如果你单击其中一个按钮 它会将UserControl加载到form1

中的面板中

usercontrol1也包含很多数据,如数据库,图表和图片框。因此,加载时肯定会使用户界面无响应。

所以我读了一些文章,我发现我需要通过另一个线程运行它,所以我尝试了它,它只是稍微提高了性能。

usercontrol1仍然会使GUI无响应约3-5秒,如果我的数据变大了怎么办。

我想让它响应并向用户显示仍然通过运行动画图片框加载并停止,如果它完成加载

这是我的代码:

private void click_dashb_Click(object sender, EventArgs e)
    {

        ParameterizedThreadStart pts = new ParameterizedThreadStart(load_UserControl);
        Thread t = new Thread(pts);
        t.Start();

        //Animated Picturebox to show user that UI is loading
        pictureBox1.Enabled = true;


        hover.Location = new Point(42, 130);
    }


    private void load_UserControl(object state)
    {

        Invoke(new Action(() =>
        {
            //load user control through another thread
            while (panel1.Controls.Count > 0)
                panel1.Controls[0].Dispose();


            Home frm = new Home();


            frm.AutoScroll = true;
            panel1.Controls.Add(frm);
            frm.Show();
        }));

        //Stop the animated GIF means the load is finish!
        pictureBox1.Enabled = false;
    }

如果你帮我解决这个问题。我可以把它应用到我的所有作品中。因为大多数都包含大数据。

感谢stackoverflow社区:)

编辑:

阅读建议使用后台工作人员的评论。我试着用它。但仍然有点无反应 这是新代码:

 private void click_dashb_Click(object sender, EventArgs e)
    {

        bgw.RunWorkerAsync();

    }
 private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {

        try
        {


            BeginInvoke((MethodInvoker)delegate
            {
                while (panel1.Controls.Count > 0)
                    panel1.Controls[0].Dispose();


                Home frm = new Home();


                frm.AutoScroll = true;
                panel1.Controls.Add(frm);
                frm.Show();
            });


        }
        catch (Exception x)
        {
            MessageBox.Show("An error occured while performing operation" + x);
        }

    }

    private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

    }

    private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            MessageBox.Show("Operation Cancelled");

        }
        else
        {

            MessageBox.Show("Operation Completed");


        }
    }

它好一点但我仍然有点反应迟钝。你能看看我的代码以及它的错误吗?

再次感谢

2 个答案:

答案 0 :(得分:0)

您的代码的问题在于,虽然您在新线程中运行load_UserControl代码,但该代码调用Invoke,这有效地使代码再次在UI线程上运行。我可以想象你这样做,因为访问Forms和PictureBoxes需要在UI线程上运行。

解决方案(通常)是在单独的线程上进行非UI工作,然后切换回UI线程以更新可视控件。

为此,您可以方便地使用BackgroundWorker类。在DoWork事件处理程序中,您执行繁重的计算,在RunWorkerCompleted事件处理程序中更新控件。如果需要,您甚至可以通过ProgressChanged事件处理程序在工作期间更新某些控件(如进度条)。

答案 1 :(得分:0)

好吧,刚开始一个新线程并没有按照定义使UI响应。你需要创建线程,以便它实际上并行执行。

你的线程没有,因为它基本上执行this.Invoke中的所有代码。

话虽如此:您的代码需要this.Invoke中执行,因为几乎所有操作都需要在UI线程上完成。

所以在你的情况下,并行化东西真的没有意义,因为在没有阻止UI线程的情况下没有办法做你想做的事情而且没有我知道的技术(线程,任务) ,BackgroundWorker等)将解决这个问题。