当我使用委托方法运行我的方法以便让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";
}
答案 0 :(得分:3)
你应该看看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
}
答案 1 :(得分:0)
与Native Win32 API或MFC不同,Dot-net框架不支持多线程UI方法的*控件调用。因此,您无法在任何线程中创建UI控件(窗口)并调用它的方法并从另一个线程设置属性! (*此处和下方 - 更新(刷新)UI上下文的UI方法。您可以从控件读取数据并且无法写入) 顺便说一句,在原生环境中,这样的调用也不能可靠地工作,有时会抛出严重管理的异常...... 但托管环境不能允许方法调用会导致异常!它只是“冻结”一个这样的电话,并没有做任何事情来刷新。 顺便提一下,平台的这个功能不仅适用于后台线程。无论是调用BeginInvoke(来自内置线程池),还是通过其他方式创建用户的非后台线程,您都会遇到同样的问题。 在您的特定情况下,我看不出有任何理由让两个或多个线程共享同一个控件 - 这在数据安全性方面也很危险。通常,其他线程(通常是并行性)用于完全不同的目的:用于任何长时间的计算,数据库,文件,网络的I / O操作。 当然,您可以在其他线程中调用一些消息框。