代码之家  ›  专栏  ›  技术社区  ›  C Walker

工作线程添加到BindingList时出现跨线程操作异常

  •  5
  • C Walker  · 技术社区  · 15 年前

    BindingList . 然而 数据绑定到 DataGridView . 所以,当我尝试添加到列表时,我得到一个 InvalidOperationException (Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on.)

    if(winformControl.InvokeRequired) {
        winformControl.Invoke(MethodDelegate);
    }
    

    然而,数据绑定混淆了事情,因为没有Winform控件。我只剩下下面一行,它抛出了一个异常:

    ClassInstance.MyBindingList.Add(myObject);
    

    如果你有一个专门针对这个场景的解决方案,那就太好了。

    如果没有,我如何让工作线程告诉我的主线程执行一个特定的方法(工作线程提供了几个参数)?这可能是一个更好的选择,因为我的工作线程目前实际上正在做一大堆事情(比如写数据库),我不确定是否所有事情都是线程安全的。我是一名学生,对多线程还不熟悉,但这还不是我的专长。

    4 回复  |  直到 15 年前
        1
  •  0
  •   ChrisF    15 年前

    您可以向main、UI和线程触发事件,并且有:

    if (this.InvokeRequired)
    {
        this.Invoke(...);
    }
    

    所以您正在主窗口本身上进行测试。

        2
  •  1
  •   Marc Gravell    15 年前

    这里的一个选择是 BindingList<T> like this -然而,这可以说不是最好的办法。我想知道您是否可以通过事件或类似的方式公开数据(而不是直接添加到列表中),然后让您的UI通过发送到正确的线程并添加到UI模型来处理事件。

        3
  •  1
  •   g t Omri Btian    13 年前

    private System.Threading.SynchronizationContext mContext = null;
    
    /// <summary>
    /// Constructor for MyBackgroundWorkerClass
    /// </summary>
    public MyBackgroundWorkerClass(System.Threading.SynchronizationContext context)
    {
        mContext = context;
    }
    

    然后,当您需要在UI线程上调用某些内容时:

    private void CallOnTheUiThread(object dataToPassToUiThread)
    {
        // Make sure the code is run on the provided thread context.
        // Make the calling thread wait for completion by calling Send, not Post.
        mContext.Send(state =>
            {
                // Change your UI here using dataToPassToUiThread.  
                // Since this class is not on a form, you probably would 
                // raise an event with the data.
            }
        ), null);
    }
    

    当从UI线程上的窗体创建worker类时,这是作为同步上下文传递的内容。

    private void Form1_Load(object sender, EventArgs e)
    {
        var worker = new MyBackgroundWorkerClass(SynchronizationContext.Current);
    }
    
        4
  •  0
  •   jdot    15 年前

    定义在后台线程(如保存到数据库)上运行的DoWork方法。当DoWork完成时调用RunWorkerCompleted方法。RunWorkerCompleted在UI线程上运行,您可以毫无问题地更新视图的列表。

    // on the UI thread
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += DoWork;
    worker.RunWorkerCompleted += RunWorkerCompleted;
    worker.RunWorkerAsync("argument");
    

    活动:

    static void DoWork(object sender, DoWorkEventArgs e)
    {
        e.Result = "4";
    }
    
    static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            string a = (string)e.Result;
            Console.WriteLine(a);
        }
        else
        {
            Console.WriteLine(e.Error.Message);
        }
    }