关于UI C#中的Winform线程
本文关键字:Winform 线程 中的 UI 关于 | 更新日期: 2023-09-27 17:57:25
当我使用委托方法来运行我的方法以让UI刷新时,UI不会刷新。我想在方法运行时阻止UI冻结,我能做什么?
private void SearchToolStripButton_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(StartMethod));
t.Start();
}
private delegate void InvokeDelegate();
public void StartMethod()
{
this.BeginInvoke(new InvokeDelegate(SearchData));
}
public void SearchData()
{
if (searchKeywordTextBox.Text == "")
{
MessageBox.Show("Please type the keyword!");
}
else
{
if (searchDateTimePicker.Checked == true)
{
switch (selectRangeComboBox.Text)
{
case "Day": showDataToresultDataGridViewOnDay(searchKeywordTextBox.Text);
break;
case "Month": showDataToresultDataGridViewInMonth(searchKeywordTextBox.Text);
break;
case "Year": showDataToresultDataGridViewInYear(searchKeywordTextBox.Text);
break;
default: MessageBox.Show("Please select a Section");
break;
}
}
else
{
showDataToresultDataGridView(searchKeywordTextBox.Text);
}
}
}
public void showDataToresultDataGridViewOnDay(string keyword)
{
DataGridView dayGrid = resultDataGridView;
ShowResultDay day = new ShowResultDay();
resultDataGridView.DataSource = day.ShowGridDay(searchDateTimePicker.Value.Day, searchDateTimePicker.Value.Month, searchDateTimePicker.Value.Year, keyword);
resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records in " + searchDateTimePicker.Value.Day + "/" + searchDateTimePicker.Value.Month + "/" + searchDateTimePicker.Value.Year;
}
public void showDataToresultDataGridViewInMonth(string keyword)
{
DataGridView monthGrid = resultDataGridView;
ShowResultMonth month = new ShowResultMonth();
resultDataGridView.DataSource = month.ShowGridMonth(searchDateTimePicker.Value.Month, searchDateTimePicker.Value.Year, keyword);
resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records in " + searchDateTimePicker.Value.Month + "/" + searchDateTimePicker.Value.Year;
}
public void showDataToresultDataGridViewInYear(string keyword)
{
DataGridView yearGrid = resultDataGridView;
ShowResultYear year = new ShowResultYear();
resultDataGridView.DataSource = year.ShowGridYear(searchDateTimePicker.Value.Year, keyword);
resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records in " + searchDateTimePicker.Value.Year;
}
public void showDataToresultDataGridView(string keyword)
{
ShowAllData all = new ShowAllData();
var results = all.ShowGirdAll(keyword);
resultDataGridView.DataSource = results;
resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records";
}
您应该了解一下BackgroundWorker
类,它是专门为使WinForms中的多线程更容易而实现的。
那么我建议另一件事:
不要从后台线程打开消息框,而是在启动线程之前检查属性和字段,然后只在非ui线程中运行搜索。
后台工作人员使用示例:
// Initialization
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
// Start elaboration
bw.RunWorkerAsync(objectArgument);
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// do your work (we are in the background-thread)
// when you have finished, set your results in the e.Result property
// N.B. don't show anything because we are in the background-thread
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// here we have finished the work (we are in the UI-thread)
// result is set in e.Result property
// N.B. check e.Error property before to get e.Result because
// if there's an error e.Result throws an exception
}
与本机Win32 API或MFC不同,Dot-net框架不支持多线程UI方法的*对控件的调用。因此,您不能在任何线程中创建UI控件(窗口)并从另一个线程调用它的方法和设置属性!(*在这里和下面-更新(刷新)UI上下文的UI方法。您可以从控件读取数据,但不能写入)顺便说一句,在本机环境中,这种调用也不能可靠地工作,有时会抛出管理不善的异常。。。但是托管环境不允许方法调用会导致异常!它只是"冻结"了一个这样的调用,而不做任何刷新操作。顺便说一句,该平台的这一功能不仅适用于后台线程。无论是调用BeginInvoke(从内置线程池),还是通过其他方式创建用户的非后台线程,都会遇到同样的问题。在您的特定情况下,我看不出有任何理由让两个或多个线程共享同一控件——这在数据安全方面也是危险的。通常,其他线程(通常是并行)用于完全不同的目的:用于任何长时间计算、数据库、文件和网络的I/O操作。当然,您也可以在其他线程中调用一些MessageBoxes。