c#线程仍然使UI无响应
本文关键字:UI 响应 线程 | 更新日期: 2023-09-27 18:14:50
嗯,我有一个有按钮的form1,如果你点击其中一个按钮它会将UserControl加载到form1
的面板中usercontrol1包含了很多数据,比如数据库、图表和图片框。所以它肯定会使用户界面在加载时无响应。
所以我读了一些文章,我发现我需要通过另一个线程运行它,所以我试了一下,它只是提高了一点性能。
usercontrol1仍然使GUI无响应大约3-5秒,如果我的数据变大了怎么办?
我想让它具有响应性并通过运行动画picturebox向用户显示仍在加载如果加载完成则停止
下面是我的代码: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");
}
}
好一点了,但还是有点反应迟钝。你能检查一下我的代码,这有什么问题吗?
再次感谢
你的代码的问题是,虽然你运行load_UserControl代码在一个新的线程,代码调用调用有效地使所有的代码运行在UI线程再次。我可以想象你这样做,因为访问表单和图片框需要在UI线程上运行。
解决方案(通常)是在一个单独的线程上完成非UI工作,然后切换回UI线程来更新视觉控件。
要做到这一点,你可以方便地使用BackgroundWorker类。在DoWork事件处理程序中,您执行繁重的计算,在RunWorkerCompleted事件处理程序中,您更新控件。如果您愿意,您甚至可以在工作期间通过ProgressChanged事件处理程序更新一些控件(如进度条)。好吧,仅仅启动一个新线程并不能使UI响应定义。你需要创建一个线程,这样它才能真正并行地做事情。
你的线程没有,因为它基本上执行this.Invoke
中的所有代码。
this.Invoke
中执行,因为几乎所有你做的事情都需要在UI线程上完成。
所以在你的情况下,并行化东西真的没有意义,因为没有办法在不阻塞UI线程的情况下做你想做的事情,而且我知道没有任何技术(线程,任务,BackgroundWorker等)可以解决这个问题。