控件 'x' 从创建它的线程以外的线程访问

Control 'x' accessed from a thread other than the thread it was created on

winform 应用程序,我有一个网格视图和数据源填充(在绑定函数上)由委托开始调用 sapareted 线程,但 gridView 数据源无法从新线程获取生成的值,因为 gridview 是在主线程上创建的:

这里我调用新线程

    private void button_selectFile_Click(object sender, EventArgs e)
    {

        if (resultLoadingFile == DialogResult.OK)
        {
            filename = openFileDialog_logLoader.FileName;
            string name = System.IO.Path.GetFileName(filename);
            label_selectFileStatus.Text = name;

            readDelegate parseAndSplit = new readDelegate(ReadLogFileAndDrawTable);
            AsyncCallback cb = new AsyncCallback(doneReadFile);
            IAsyncResult ar = parseAndSplit.BeginInvoke(filename, cb, dataGridView_mainTable);
        }
    }

这里我调用bind:

    private void doneReadFile(IAsyncResult ar)
    {
        Bind();
    }

这是 Bind():

private void Bind(){
        TableLoadMgr.ItemsLoaded = TableModelListFiltered.Count();
        updateLoadedStatus();
        //The following line throw exception:
        dataGridView_mainTable.DataSource = TableModelListFiltered;
    }

确切的问题是: 我如何在主线程上触发 Bind(),因为回调函数在新的委托线程上触发。

备注:

  1. 我看到的重复主题问题没有回答 winform 和约束
  2. 计时器不是一个选项
  3. 新用户触发器(例如线程完成后的按钮 "show")不是一个选项

您的 AsyncResult 将有一个 AsyncState,它包含对您的 DataGridView 的引用。因此,您可以使用该控件来检查 Bind() 是否需要上下文切换,如果是,则使用该控件的 Invoke 来切换线程:

private void doneReadFile(IAsyncResult ar)
{
    var ctl = ar.AsyncState as System.Windows.Forms.Control; // the control
    if (ctl != null && ctl.InvokeRequired) { // is Invoke needed?
        // call this method again, but now on the UI thread.
        ctl.Invoke(new Action<IAsyncResult>(doneReadFile), ar);
    } else {
       Bind();
    }
}