我想在数据网格视图中显示表单加载的一些数据,我想要显示的数据是大量行,当我使用后台工作程序处理器时,它显示以下错误。
我的代码:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
dataGridViewRequest.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.DataSource = obj.ListResponseFiles();
dataGridViewResponses.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
表单加载:
private void FormFTP_Load(object sender, EventArgs e)
{
try
{
//this.comboBoxRequests.SelectedIndex = 0;
backgroundWorker1.RunWorkerAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
答案 0 :(得分:3)
有许多不同的方法可以防止表格被冻结 例如,您可以像这样加载数据:
private async void Form_Load(object sender, EventArgs e)
{
//do some initializations
await LoadData();
//do some other initializations that you need to perform.
}
private async Task LoadData()
{
//Load your data here
//For example
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
}
这种方式在运行表单时,命令按照您在UI响应时编写的顺序运行,并且您不会遇到使用BackgroundWorker
或交叉线程操作异常等线程的常见困难。
关键是使用async / await。有关详细信息,请参阅Asynchronous Programming with Async and Await
请记住,这样,每个你想调用LoadData的地方,都应该这样称呼它:
await LoadData();
您编写此代码的方法应该是异步的:
private async void RefreshButton_Click(object sender, EventArgs e)
{
await LoadData();
}
编辑.Net 4.0
对于.Net 4.0,您可以同时使用Task.Run
或BackgroundWorker
。我推荐Task.Run
,因为它更简单,更易读。
请注意,当您从除UI之外的其他线程访问UI元素时,将抛出交叉线程操作异常。在这种情况下,您应该使用this.Invoke(new Action(()=>{/*Access UI Here*/}));
代替。永远不要在你的调用部分中放置一个耗时的任务。
BackgroundWorker方法:
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
//If you put some code here for example MessageBox.Show("");
//The code will immadiately run and don't wait for worker to complete the task.
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
this.LoadData();
}
public void LoadData()
{
var ftp = new FtpUtility();
var data = ftp.ListRequestFiles();
this.Invoke(new Action(() =>
{
//Setup columns and other UI stuff
//Set datasource of grid
this.dataGridView1.DataSource = data;
}));
}
LoadData
,现在您应该使用backgroundWorker1.RunWorkerAsync();
。backgroundWorker1_RunWorkerCompleted
或Invoke
LoadData
部分。Task.Run方法
private void Form1_Load(object sender, EventArgs e)
{
Task.Run(() =>
{
LoadData();
})
.ContinueWith(x =>
{
//You can put codes you want run after LoadData completed here
//If you access the UI here, you should use Invoke
});
//If you put some code here for example MessageBox.Show("");
//The code will immadiately run and don't wait for worker to complete the task.
}
public void LoadData()
{
var ftp = new FtpUtility();
var data = ftp.ListRequestFiles();
this.Invoke(new Action(() =>
{
//Setup columns and other UI stuff
//Set datasource of grid
this.dataGridView1.DataSource = data;
}));
}
LoadData
,现在您应该使用Task.Run(()=>{LoadData();});
。LoadData
完成后完成工作,请将您的工作放在ContinueWith
或Invoke
LoadData
部分。答案 1 :(得分:1)
试试这个。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
dataGridViewRequest.Invoke(new Action(() => {
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
dataGridViewRequest.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.DataSource = obj.ListResponseFiles();
dataGridViewResponses.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormFTP_Load(object sender, EventArgs e)
{
try
{
//this.comboBoxRequests.SelectedIndex = 0;
backgroundWorker1.RunWorkerAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}