【发布时间】:2017-01-30 19:45:09
【问题描述】:
我正在制作一个相对基本的WinForms 用户控件,其中包含许多按钮,每个按钮代表数据库中的一个表。
在调用InitializeComponent方法后,每个表中的数据被加载到对应的DataGridView中。
当单击上述按钮之一时,其对应的DataGridView 以及那些通过 FK 链接到主按钮的代表表变得可见,然后 BackgroundWorker 逐渐将它们增加到所需的大小并将控件转移到适当的位置在短时间内。
public uc1()
{
InitializeComponent();
PopulateTables();
tableResizer.WorkerReportsProgress = true;
tableResizer.WorkerSupportsCancellation = true;
tableResizer.DoWork += tableResizer_DoWork;
tableResizer.ProgressChanged += tableResizer_ProgressChanged;
tableResizer.RunWorkerCompleted += tableResizer_RunWorkerCompleted;
dgv5.SelectionChanged += show5Relations;
}
private void btn5_Click(object sender, EventArgs e)
{
mainTable = 5;
btn5.Visible = false;
btn4.Visible = false;
btn3.Visible = false;
btn2.Visible = false;
dgv5.Visible = true;
dgv4.Visible = true;
dgv3.Visible = true;
dgv2.Visible = true;
lbl6.Visible = false;
lbl7.Visible = false;
lbl1.Visible = false;
tableResizer.RunWorkerAsync();
}
private void tableResizer_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
int expansion = 0;
while (expansion < 30)
{
tableResizer.ReportProgress(mainTable);
expansion++;
System.Threading.Thread.Sleep(16);
}
}
private void tableResizer_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 5)
{
dgv5.Size = new Size(dgv5.Size.Width + (((this.Width / 26) * 10) / 30), dgv5.Size.Height + (((this.Height / 24) * 10) / 30));
dgv5.Location = new Point(dgv5.Location.X - (((this.Width / 26) * 10) / 60), dgv5.Location.Y - (((this.Height / 24) * 10) / 60));
dgv4.Size = new Size(dgv4.Size.Width + (((this.Width / 26) * 10) / 30), dgv4.Size.Height + (((this.Height / 24) * 10) / 50));
dgv4.Location = new Point(dgv4.Location.X - (((this.Width / 26) * 10) / 40), dgv4.Location.Y - (((this.Height / 24) * 10) / 120));
dgv3.Size = new Size(dgv3.Size.Width + (((this.Width / 26) * 10) / 30), dgv3.Size.Height + (((this.Height / 24) * 10) / 50));
dgv3.Location = new Point(dgv3.Location.X - (((this.Width / 26) * 10) / 40), dgv3.Location.Y - (((this.Height / 24) * 10) / 120));
dgv2.Size = new Size(dgv2.Size.Width + (((this.Width / 26) * 10) / 30), dgv2.Size.Height + (((this.Height / 24) * 10) / 50));
dgv2.Location = new Point(dgv2.Location.X - (((this.Width / 26) * 10) / 40), dgv2.Location.Y - (((this.Height / 24) * 10) / 120));
btn1.Location = new Point(btn1.Location.X - (((this.Width / 26) * 10) / 130), btn1.Location.Y);
}
}
private void tableResizer_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (mainTable == 5)
{
btn7.Visible = true;
btn6.Visible = true;
btn1.Visible = true;
lbl5.Visible = true;
lbl5.Location = new Point(dgv5.Location.X, dgv5.Location.Y - lbl5.Size.Height);
lbl4.Visible = true;
lbl4.Location = new Point(dgv4.Location.X, dgv4.Location.Y - lbl4.Size.Height);
lbl3.Visible = true;
lbl3.Location = new Point(dgv3.Location.X, dgv3.Location.Y - lbl3.Size.Height);
lbl2.Visible = true;
lbl2.Location = new Point(dgv2.Location.X, dgv2.Location.Y - lbl1.Size.Height);
}
}
问题在于,当tableResizer 工作时,UI 的渲染速度不够快,因此,DataGridViews 之一在工作完成之前无法完全可见。
在DoWork 方法中增加睡眠的长度仅在 60 毫秒时解决了这个问题,此时渲染太不稳定而无法接受。任何超过 30 毫秒的都不会做。
我对多线程和 C# 比较陌生,所以我很确定有更有效的方法来解决这个问题。
我应该怎么做才能保证流畅的渲染?
【问题讨论】:
-
如果您使用
BackgroundWorker只是动画,那么请改用System.Timers.Timer或System.Threading.Timer。
标签: c# .net multithreading winforms