C#中BeginInvoke调用无响应问题求助(跨线程UI场景)
解决跨线程调用Refresh方法无响应的问题
首先咱们拆解你遇到的问题:FileSystemWatcher的事件确实运行在非UI线程,你用BeginInvoke的思路是对的,但没生效大概率是几个细节没处理到位,咱们一步步来修复:
1. 先修正最容易忽略的语法错误
你的Refresh()方法里的SQL语句有个明显笔误:
string Query = "SELECT a, v, b, cFROM note Where Servizio_ID = " + asd+ " AND Visibile = 1 order by ID desc limit 15 OFFSET " + (pageIndex * page) + " ;";
cFROM中间缺少空格,应该改成c FROM——这个语法错误会导致SQL执行失败,而因为你用的是BeginInvoke异步调用,异常会被悄悄吞掉,看起来就像Refresh没执行一样。先把这个问题解决!
2. 确保Invoke调用的是正确的UI控件
你当前用this.BeginInvoke,如果this不是在UI线程创建的窗体/控件,或者该对象已被销毁,BeginInvoke就不会生效。更稳妥的方式是直接用你要操作的UI控件(也就是noteContainer)来调用Invoke,因为它肯定是UI线程创建的:
把原来的:
this.BeginInvoke(new InvokeDelegate(Refresh));
替换成以下代码,同时加上InvokeRequired判断和异常捕获,方便排查问题:
// 直接用要操作的UI控件来判断和调用 if (noteContainer.InvokeRequired) { try { // 先尝试同步Invoke,这样如果有异常会直接抛出,方便排查 noteContainer.Invoke(new Action(Refresh)); // 如果后续需要异步,再改成BeginInvoke,记得加回调捕获异常 // noteContainer.BeginInvoke(new Action(Refresh), ar => // { // if (ar.Exception != null) // { // MessageBox.Show($"异步调用异常: {ar.Exception.Message}"); // } // }, null); } catch (Exception ex) { MessageBox.Show($"调用Refresh失败: {ex.Message}"); } } else { // 已经在UI线程,直接调用 Refresh(); }
3. 确认代码真的走到了Invoke分支
你的OpenFormNewNote方法里有loop变量的逻辑,只有当loop == 2时才会执行后续代码,而且FileSystemWatcher的Change事件可能会触发多次(比如文件创建时可能触发Changed、Created两次),你可以加个临时调试输出,确认result == DialogResult.OK的条件确实被满足:
if(result == DialogResult.OK) { MessageBox.Show("OK分支触发,准备调用Refresh"); // 临时调试用,后续可删除 // 这里放上面修改后的Invoke代码 }
4. 额外提醒:修复SQL注入风险
你的SQL语句直接拼接asd变量,存在严重的SQL注入风险,建议改成参数化查询:
string Query = "SELECT a, v, b, c FROM note Where Servizio_ID = @ServizioId AND Visibile = 1 order by ID desc limit 15 OFFSET @Offset;"; MySqlCommand MyCommand = new MySqlCommand(Query, MyConn); MyCommand.Parameters.AddWithValue("@ServizioId", asd); MyCommand.Parameters.AddWithValue("@Offset", pageIndex * page);
按照上面的步骤修改后,应该就能正常触发Refresh方法了。
内容的提问来源于stack exchange,提问作者Alessio Trecani
相关产品推荐
相关产品推荐

