C# Win Form - 使用后台工作者时主线程没有响应
C# Win Form - Main thread not responding when using background worker
我有一个 datagridview,它由 DataTable 通过 DataSource 填充,我正在使用 backgroundworker 用于格式化 datagridview 中的单元格(单元格的背景颜色和前景色)。
BackgroundWorker bw = new BackgroundWorker();
private void Frm_Find_Load(object sender, EventArgs e)
{
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
CheckForValidValues();
}
public bool CheckForValidValues()
{
dgv.Invoke((MethodInvoker)delegate()
{
for (int i = 0; i < Dt.Rows.Count; i++)
{
if (Dt.Rows[0]["Name"].ToString() == Value)
{
dgv.Rows[i].Cells["Name"].Style.BackColor = Color.FromArgb(255, 192, 192);
}
else
{
dgv.Rows[i].Cells["Name"].Style.BackColor = Color.White;
}
progressBar1.Invoke((MethodInvoker)(() => progressBar1.Value++));
}
});
this.Invoke((MethodInvoker)delegate()
{
BtnShow.Enabled = true;
dgv.Enabled = true;
});
}
private void btnSave_Click(object sender, EventArgs e)
{
if (bw.IsBusy == false)
{
progressBar1.Visible = true;
progressBar1.Value = 0;
BtnShow.Enabled = false;
dgv.Enabled = false;
progressBar1.Maximum = dgv.Rows.Count;
bw.RunWorkerAsync();
}
}
虽然整个过程都停止了,但 DataGridView 仍然存在 Enabled=false
,因此用户无法更改 datagridview 中的任何值。
datagridview 中通常有 15,000 行,那么多行要格式化,这需要时间,这就是为什么我为其使用 backgroundworker 并且它工作正常非常好 但是当用户尝试按 enabled false datagridview 几次,主线程变得无响应并且进度条冻结。
谁能指导我如何处理?
也许尝试在按钮被点击时禁用它直到完成工作?
假设您的按钮名称是 Button1,
当用户点击 Enabled false data grid view,使用 Button.enabled=false,然后当作业完成时使用 Button.enabled=true
希望对您有所帮助!
你是运行整个代码使用Invoke
。这意味着您正在切换到 UI 线程并且代码是 运行 in UI 线程。由于代码是一个耗时的 for
循环,因此它阻塞了 UI 个线程。
与其使用 BackgroundWorker
格式化单元格,不如使用 CellFormatting
事件:
private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//If this is header cell or new row, do nothing
if (e.RowIndex < 0 || e.ColumnIndex < 0 || e.RowIndex == dgv.NewRowIndex)
return;
//If formatting your desired column, perform validation
if (e.ColumnIndex == dgv.Columns["Name"].Index)
{
// Perform validation and change cell back color here.
}
}
我有一个 datagridview,它由 DataTable 通过 DataSource 填充,我正在使用 backgroundworker 用于格式化 datagridview 中的单元格(单元格的背景颜色和前景色)。
BackgroundWorker bw = new BackgroundWorker();
private void Frm_Find_Load(object sender, EventArgs e)
{
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
CheckForValidValues();
}
public bool CheckForValidValues()
{
dgv.Invoke((MethodInvoker)delegate()
{
for (int i = 0; i < Dt.Rows.Count; i++)
{
if (Dt.Rows[0]["Name"].ToString() == Value)
{
dgv.Rows[i].Cells["Name"].Style.BackColor = Color.FromArgb(255, 192, 192);
}
else
{
dgv.Rows[i].Cells["Name"].Style.BackColor = Color.White;
}
progressBar1.Invoke((MethodInvoker)(() => progressBar1.Value++));
}
});
this.Invoke((MethodInvoker)delegate()
{
BtnShow.Enabled = true;
dgv.Enabled = true;
});
}
private void btnSave_Click(object sender, EventArgs e)
{
if (bw.IsBusy == false)
{
progressBar1.Visible = true;
progressBar1.Value = 0;
BtnShow.Enabled = false;
dgv.Enabled = false;
progressBar1.Maximum = dgv.Rows.Count;
bw.RunWorkerAsync();
}
}
虽然整个过程都停止了,但 DataGridView 仍然存在 Enabled=false
,因此用户无法更改 datagridview 中的任何值。
datagridview 中通常有 15,000 行,那么多行要格式化,这需要时间,这就是为什么我为其使用 backgroundworker 并且它工作正常非常好 但是当用户尝试按 enabled false datagridview 几次,主线程变得无响应并且进度条冻结。
谁能指导我如何处理?
也许尝试在按钮被点击时禁用它直到完成工作?
假设您的按钮名称是 Button1,
当用户点击 Enabled false data grid view,使用 Button.enabled=false,然后当作业完成时使用 Button.enabled=true
希望对您有所帮助!
你是运行整个代码使用Invoke
。这意味着您正在切换到 UI 线程并且代码是 运行 in UI 线程。由于代码是一个耗时的 for
循环,因此它阻塞了 UI 个线程。
与其使用 BackgroundWorker
格式化单元格,不如使用 CellFormatting
事件:
private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//If this is header cell or new row, do nothing
if (e.RowIndex < 0 || e.ColumnIndex < 0 || e.RowIndex == dgv.NewRowIndex)
return;
//If formatting your desired column, perform validation
if (e.ColumnIndex == dgv.Columns["Name"].Index)
{
// Perform validation and change cell back color here.
}
}