TextBox TextChanged结合BackgroundWorker填充DataGridView遇并发错误求助
解决BackgroundWorker并发运行报错及实时搜索优化方案
我在窗体中使用TextBox、BackgroundWorker和DataGridView控件,希望通过TextBox的TextChanged事件触发BackgroundWorker查询匹配数据,实时填充DataGridView。但运行后报错:
ErrorSystem.InvalidOperationExceptoin:This Background worker is currently busy and cannot run multiple tasks concurrently.
错误原因
CancelAsync()仅发送取消请求,不会立即终止正在执行的DoWork线程,此时IsBusy仍为true,直接调用RunWorkerAsync()会触发并发冲突。DoWork方法中直接访问UI控件txtSearchBox.Text,违反WinForms线程安全规则(后台线程禁止直接操作UI)。- 存在SQL注入风险,且数据库连接未正确释放。
解决方案及修正代码
核心修复点
- 等待后台线程真正完成取消后再启动新任务
- 通过参数传递查询文本,避免后台线程访问UI控件
- 在
DoWork中响应取消请求,及时终止操作 - 使用参数化查询避免SQL注入,用
using管理数据库连接
1. TextChanged事件处理
private void txtSearchBox_TextChanged(object sender, EventArgs e) { if (backgroundWorker1.IsBusy) { backgroundWorker1.CancelAsync(); // 等待线程真正结束,同时保持UI响应 while (backgroundWorker1.IsBusy) { Application.DoEvents(); } } // 将搜索文本作为参数传入后台线程 backgroundWorker1.RunWorkerAsync(txtSearchBox.Text.Trim()); }
2. DoWork事件处理
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { string searchText = e.Argument as string; // 检查取消请求,及时终止 if (backgroundWorker1.CancellationPending) { e.Cancel = true; return; } DataSet ds = new DataSet(); // 使用using自动释放数据库连接和适配器 using (MySqlConnection con = new MySqlConnection("你的数据库连接字符串")) { try { con.Open(); // 参数化查询,避免SQL注入 string sql = "SELECT * FROM Games WHERE Name LIKE @SearchText"; MySqlDataAdapter da = new MySqlDataAdapter(sql, con); da.SelectCommand.Parameters.AddWithValue("@SearchText", $"%{searchText}%"); da.Fill(ds, "GameID"); // 填充后再次检查取消状态 if (backgroundWorker1.CancellationPending) { e.Cancel = true; return; } // 将查询结果传递给完成事件 e.Result = ds.Tables["GameID"]; } catch (Exception ex) { // 将异常信息传递到完成事件处理 e.Result = ex; } } }
3. RunWorkerCompleted事件处理
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // 任务被取消则直接返回 if (e.Cancelled) { return; } // 处理查询异常 if (e.Result is Exception ex) { MessageBox.Show($"查询出错:{ex.Message}"); return; } // 更新DataGridView数据源 DataTable dt = e.Result as DataTable; if (dt != null) { SimilarData.DataSource = dt.DefaultView; } }
额外优化建议
- 添加输入延迟(如300ms),避免用户每输入一个字符就触发查询,减少数据库请求频率
- 确保BackgroundWorker的
WorkerSupportsCancellation属性设置为true(可在设计器或构造函数中配置)
内容的提问来源于stack exchange,提问作者RayMond
相关产品推荐
相关产品推荐

