网上的解决方案:http://blog.csdn.net/jumtre/article/details/44927271
1:设置 CheckForIllegalCrossThreadCalls false
2:委托
3:用BeginInvoke 或者异步线程
为什么我用了线程还是提示这个错误呢 不明白 看代码
void GetInstance_storeSelectChanged(object sender, StoreSelectChangedEventArgs e) { if (IsOk) return; var temp=frmMain.GetInstance.dialog.Entity;; if (temp == null || temp.Count == 0) return; var sourceno = temp.Aggregate("", (current1, xxx) => current1 + (xxx.sourceno + ",")).TrimEnd(','); Task.Factory.StartNew(() => { var matappList = Voion.Core.SqlClientFactory.Instance.Query<matapp_dl>("SELECT * FROM matapp_dl WHERE docno=@docno", new { docno = sourceno }); if (matappList == null || matappList.Count == 0) return; foreach (var tagetModel in matappList) { var outlist = new stotheroutlst_pro { zbid = tagetModel.zbid, keyno = tagetModel.zbid, code = tagetModel.proitemno, productno = tagetModel.productno, seqno = 0, proitemno = tagetModel.proitemno, appqty = 1, numb = 2, lostqty = tagetModel.lostqty, sheetsqty = 3, prosheetsqty = 4, needqty = tagetModel.needqty, needsheetqty = 5, outno = "a", active_id = 6, stock_id = 7, userid = User.Idno, inputdate = DateTime.Now, sizelost = 6, retqty = tagetModel.Waitretqty, appid = 100 }; Entity.StotherOutlstProList.Add(outlist); } bindingSource.ResetBindings(false); var thread = new Thread(() => { gridView1.RefreshData(); }); thread.Start(); }); IsOk = true; }
错误的意思是 不是在UI线程修改了这个控件 。
GetInstance_storeSelectChanged是注册事件回调函数
报错的地方
gridView1.RefreshData(); 我已经用线程里面就是一个委托 怎么还是这个 错误呢。 不明白
method<T>(T c,Action<T> action) where T:Control
{
if(InvokeRequired)
{
Invoke(new Action(()=>action(c));
}
else
action(c);
}
bindingSource.ResetBindings(false);
method(gridView1,view=>view.RefreshData());
这个Control改成 DevExpress.XtraGrid.Views.Grid.GridView
dev的 问题又来了
Cross thread operation detected. To suppress this exception, set DevExpress.Data.CurrencyDataController.DisableThreadingProblemsDetection = true
我设置ture和flase都是这个
玩不来
还是改成task 等待 成功后执行 gridView1.RefreshData();
大神没解释我的为什么不行嗯?
@s_p: bindingSource是啥?
你改成委托,不是要你额外拉一个线程去干这个事,而是要ui线程来干这个事
@Daniel Cai: bindingSource 是winfrom 后面新出的一绑定控件的方法。 以前直接是 xx.datasocre=xx;
现在是加了个中间的通道。 有的类似wpf里面的双向绑定。
@s_p: 把bindingSource也用上面相同的方法包一下。
@Daniel Cai: 写个类似 method 这个 改成 bindingSource的?
@s_p: 你这些第三方控件应该都是从Control下派生出来的啊。直接用我前面贴的那个就可以了。
@Daniel Cai: 可以了 解决了 是的 bindingSource不要也会报错误。
用control 会提升类型无法转换。我就直接用他的类型了。
private void method<T>(T c, Action<T> action) where T : DevExpress.XtraGrid.Views.Grid.GridView { if (InvokeRequired) { Invoke(new Action(() => action(c))); } else action(c); }
同样 bindingSource 的也是类似
没有报错了 谢谢了 大神。
@Daniel Cai: 不是要你额外拉一个线程去干这个事,而是要ui线程来干这个事 这句话理解 我知道要让ui线程去干事 。可是网上的都是这样给的答案 委托 在里面 还是不是ui线程? 详细点 老鸟。
@s_p:委托只是事情怎么做,但谁来做这是个问题。按你的写法你的委托其实就是
()=>gridview.RefreshData()。
而由于winform这种玩意都是基于消息循环的,其要求ui上控件的更新必须要ui线程来执行才行,那么你额外那个thread跑肯定是不行的,所以必须要绕,在那个method的方法内会做一次判断(this.InvokeRequired),如果为true则表示需要invoke方式来执行(也就是if内部那句代码),所谓的需要invoke方式执行也就是control发现当前执行线程不是创建control的线程,那么只能告诉控件我有件事要做,你那边如果可以的话就执行下(Invoke(....)),当创建控件的线程被invoke了后进入这个判断就直接跳到了else中去把对应的委托方法执行了(也就是refreshdata)
@s_p: 另
method<GridView>(gridView1,gd=>gd.RefreshData());
method<TextBox>(tb,tb=>tb.Text="hello world");
按理说应该可以省略显式的泛型类型指定的啊。
@Daniel Cai: 是的 去掉 约束 where T:XXXX也可以 我看你写的 这个 就是约束 在编译时发现错误。
@s_p: 恩,那个约束可以去掉。
@Daniel Cai: 谢谢了。(*^__^*) ……