我正在将数据从我的数据表加载到我的应用程序的datagridview中。在执行此操作时,我想通知用户应用程序仍在通过第二个表单运行,其中进度条显示其进度,而标签包含有关已经加载到数据网格中的行数的信息。
我知道将数据加载到应用程序将冻结我的GUI,所以我决定使用第二种形式,我从我的主要任务调用它。
我打电话
Task task = new Task(LeftJoinTables);
task.Start();
然后在LeftJoinTables
我将运行此代码
...
foreach(DataRow rows in FileJoinMail.Rows)
{
wfrm.UpdateProgressBar(++i);
dataGridView1.Rows.Add(
false, //Checkbox
rows["Fullpath"],
rows["Filename"],
rows["File Size"],
rows["UserID"],
rows["E-Mail"],
rows["Date"]);
wfrm.ProcInfo($@"Loading Data [{i.ToString()}/{count.ToString()}]");
}
在我的第二个表单类中,我得到了这个方法,它调用Waitform,它更新Progressbar和带有信息的标签
public void ProcInfo(string message)
{
this.Invoke((MethodInvoker)delegate
{
ProcInfoLabel.Text = message;
});
}
public void UpdateProgressBar(int value)
{
this.Invoke((MethodInvoker)delegate
{
ProcBar.Value = value;
});
}
但从这一点来说,我得到了一个线程冲突的线程..我以为使用invoke会解决这个问题..
基本上,Windows UI(及其中的控件)使用消息泵(队列)进行更新,并且为了使其正常工作,应该已经创建了控件的句柄。确保这一点的一种简单方法是确保您的表单可见(并且因为它是一个进度条,它应该是可见的)。
private void button1_Click(object sender, EventArgs e)
{
wfrm.Show(); // make sure you are making the form visible before updating
Task task = new Task(LeftJoinTables);
task.Start();
}
private void LeftJoinTables()
{
wfrm.ProcInfo("test");
}
此外,您更新数据网格的调用也需要调用。
如果要强制创建控件句柄而不显示它,可以使用以下内容(取自https://blogs.msdn.microsoft.com/mapo/2011/04/27/forcing-handle-creation-in-a-net-windows-forms-control/):
if (!mycontrol.IsHandleCreated)
{
// This call forces creation of the control's handle.
IntPtr handle = mycontrol.Handle;
}