我在c#应用程序中有一个后台工作器和一个DataGrid。在我的Backgroundworker的工作中,它将调用我的dll中的Api,它将在SQLite数据库中输入一些数据。完成我的Api调用后,我会报告我的Backgroundworker的进度和进行中事件,我从Db获取内容并将其作为DataSource分配给我的网格。我在同一个背景工作者中调用相同的API。在处理我的应用程序崩溃的过程中。但是,如果我不在ProgressChanged中分配dataSource,我的应用程序不会崩溃。
答案 0 :(得分:4)
我假设您必须使用Invoke方法访问UI对象。
如果没有尝试使用以下方法(在拥有控件的底层窗口句柄的线程上执行指定的委托,使用指定的参数列表。):
//In Form.Designer.cs
Label myLabel = new Label();
//In code behind under Background worker method
LabelVlaueSetter SetLabelTextDel = SetLabelText;
if (myLabel .InvokeRequired)
{
myLabel.Invoke(SetLabelTextDel, "Some Value");
}
private delegate void LabelVlaueSetter(string value);
//Set method invoked by background thread
private void SetLabelText(string value)
{
myLabel.Text = value;
}
答案 1 :(得分:2)
正如Johnathan Allen所提到的,这应该不重要。除非发生其他事情。我有两种情况,我无法与BackgroundWorker
生成的事件中的某些控件进行交互。唯一有效的方法是使用Invoke
方法。
尝试在创建DataSource
控件的同一线程上分配DataGridView
。您可以通过控件的Invoke
方法执行此操作。使用以下代码。 (我没有测试过,但这是标准模式。)
如果这不起作用,请尝试Jonathan Allen的建议。
实际上,无论哪种建议最容易先尝试。
private delegate void SetDataSourceDelegate(object value);
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
DataTable oData = null; //'assign data source
if (dataGridView1.InvokeRequired) {
dataGridView1.Invoke(new SetDataSourceDelegate(SetDataSource), new Object[] {oData});
}else{
SetDataSource(oData);
}
}
private void SetDataSource(object value) {
dataGridView1.DataSource = value;
}
答案 2 :(得分:1)
应该没关系,但为什么使用ProgressChanged而不是RunWorkerCompleted?
此外,尝试在没有BackgroundWorker的情况下在GUI线程上执行所有操作。如果您的代码中存在问题或代码与GUI交互的方式,那将告诉您。