首页 新闻 会员 周边 捐助

线程间操作无效: 从不是创建控件“XXX”的线程访问它。问题 路过的朋友帮忙看下

0
悬赏园豆:10 [已解决问题] 解决于 2016-11-24 16:32

网上的解决方案: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(); 我已经用线程里面就是一个委托 怎么还是这个 错误呢。 不明白
s_p的主页 s_p | 初学一级 | 园豆:140
提问于:2016-11-24 14:44
< >
分享
最佳答案
0

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());

收获园豆:10
Daniel Cai | 专家六级 |园豆:10424 | 2016-11-24 14:50

这个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 | 园豆:140 (初学一级) | 2016-11-24 15:07

@s_p: bindingSource是啥?

你改成委托,不是要你额外拉一个线程去干这个事,而是要ui线程来干这个事

Daniel Cai | 园豆:10424 (专家六级) | 2016-11-24 15:19

@Daniel Cai: bindingSource 是winfrom 后面新出的一绑定控件的方法。 以前直接是 xx.datasocre=xx;

现在是加了个中间的通道。  有的类似wpf里面的双向绑定。

s_p | 园豆:140 (初学一级) | 2016-11-24 15:28

@s_p: 把bindingSource也用上面相同的方法包一下。

Daniel Cai | 园豆:10424 (专家六级) | 2016-11-24 15:47

@Daniel Cai: 写个类似 method 这个 改成 bindingSource的?

s_p | 园豆:140 (初学一级) | 2016-11-24 15:48

@s_p: 你这些第三方控件应该都是从Control下派生出来的啊。直接用我前面贴的那个就可以了。

Daniel Cai | 园豆:10424 (专家六级) | 2016-11-24 15:53

@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 的也是类似 

没有报错了 谢谢了 大神。

s_p | 园豆:140 (初学一级) | 2016-11-24 15:59

@Daniel Cai: 不是要你额外拉一个线程去干这个事,而是要ui线程来干这个事 这句话理解 我知道要让ui线程去干事 。可是网上的都是这样给的答案 委托 在里面 还是不是ui线程? 详细点 老鸟。

s_p | 园豆:140 (初学一级) | 2016-11-24 16:01

@s_p:委托只是事情怎么做,但谁来做这是个问题。按你的写法你的委托其实就是

()=>gridview.RefreshData()。

而由于winform这种玩意都是基于消息循环的,其要求ui上控件的更新必须要ui线程来执行才行,那么你额外那个thread跑肯定是不行的,所以必须要绕,在那个method的方法内会做一次判断(this.InvokeRequired),如果为true则表示需要invoke方式来执行(也就是if内部那句代码),所谓的需要invoke方式执行也就是control发现当前执行线程不是创建control的线程,那么只能告诉控件我有件事要做,你那边如果可以的话就执行下(Invoke(....)),当创建控件的线程被invoke了后进入这个判断就直接跳到了else中去把对应的委托方法执行了(也就是refreshdata)

Daniel Cai | 园豆:10424 (专家六级) | 2016-11-24 16:21

@s_p: 另

method<GridView>(gridView1,gd=>gd.RefreshData());

method<TextBox>(tb,tb=>tb.Text="hello world");

按理说应该可以省略显式的泛型类型指定的啊。

Daniel Cai | 园豆:10424 (专家六级) | 2016-11-24 16:23

@Daniel Cai: 是的 去掉 约束 where T:XXXX也可以  我看你写的 这个 就是约束  在编译时发现错误。

s_p | 园豆:140 (初学一级) | 2016-11-24 16:28

@s_p: 恩,那个约束可以去掉。

Daniel Cai | 园豆:10424 (专家六级) | 2016-11-24 16:32

@Daniel Cai: 谢谢了。(*^__^*) ……

s_p | 园豆:140 (初学一级) | 2016-11-24 16:32
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册