我第一次运行我的后台工作时它正确运行 - 在后台更新数据表,然后RunWorkerCompleted将数据表设置为datagridview数据源。
如果我再次运行它,datagridview会清除并且不会更新。我无法理解为什么。
我已经验证了当我的代码命中dgvReadWrites.DataSource时,数据表包含行。
private void btnGenerateStats_Click(object sender, EventArgs e)
{
dtJobReadWrite.Columns.Clear();
dtJobReadWrite.Rows.Clear();
dgvReadWrites.DataSource = dtJobReadWrite;
List<Tuple<string, string>>jobs = new List<Tuple<string, string>>();
foreach (ListViewItem job in lstJobs.SelectedItems)
{
jobs.Add(new Tuple<string, string>(job.Text, job.SubItems[2].Text));
}
BackgroundWorker bgw = new BackgroundWorker();
bgw.WorkerReportsProgress = true;
bgw.WorkerSupportsCancellation = true;
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
pbarGenStats.Style = ProgressBarStyle.Marquee;
pbarGenStats.MarqueeAnimationSpeed = 30;
pbarGenStats.Visible = true;
bgw.RunWorkerAsync(jobs);
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bgw = sender as BackgroundWorker;
List<Tuple<string, string>> jobs = (List<Tuple<string, string>>)e.Argument;
GetReadWriteStats(jobs);
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorker bgw = sender as BackgroundWorker;
bgw.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
bgw.DoWork -= new DoWorkEventHandler(bgw_DoWork);
pbarGenStats.MarqueeAnimationSpeed = 0;
pbarGenStats.Value = 0;
pbarGenStats.Visible = false;
dgvReadWrites.DataSource = dtJobReadWrite;
dgvReadWrites.Visible = true;
dgvReadWrites.Refresh();
}
答案 0 :(得分:3)
private void btnGenerateStats_Click(object sender, EventArgs e)
{
//...
dgvReadWrites.DataSource = dtJobReadWrite;
// etc...
}
这是一个问题,你正在更新BGW中的 dtJobReadWrite 。这会导致绑定网格由工作线程更新。非法的控件不是线程安全的,只能从创建它们的线程更新。通常会检查它,在调试时产生InvalidOperationException,但此检查不适用于绑定控件。
接下来出现了什么问题,你很幸运,你有一个高度可重复的死锁。更常见的不当行为是偶尔的绘画工件,只有在你不靠近时才会出现僵局。修正:
dgvReadWrites.DataSource = null;
并在RunWorkerCompleted事件处理程序中重新绑定网格,就像您已经这样做。
答案 1 :(得分:0)
因为您取消订阅这些活动
bgw.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
bgw.DoWork -= new DoWorkEventHandler(bgw_DoWork);
删除这些行
答案 2 :(得分:0)
为什么每次要运行它时都要创建一个新的BackgroundWorker?我想看看如果您使用BackgroundWorker的一个实例(GetReadWriteWorker或其他类似的东西),只需订阅一次事件,然后在btnGenerateStats_Click上运行该工作程序Async,此代码会发生什么。