2

winform app, i have a grid view and the datasource populate (on bind function) by delegate begin invoke sapareted thread, but the gridView DataSource cannot get the generated value from the new thread because the gridview was created on Main Thread:

Here i invoke new thread

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

Here i call bind:

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

And this is Bind():

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

enter image description here enter image description here The exacly question is: How do i fire Bind() on the Main Thread since the callback function fire on the new delegate thread.

Remarks:

  1. Duplicate subject question i saw didn't answer winform and the constraints
  2. Timer is not an option
  3. new user trigger (such button "show" after thread complete) is no an option
shdr
  • 868
  • 10
  • 25
  • 1
    Which duplicate subject question did you look at? [This one](https://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) maybe and you're sure none of the 34 answers there worked in your context? – rene Jun 18 '18 at 09:26
  • Does that potential duplicate help or not? Because otherwise I miss what is different in your context. – rene Jun 18 '18 at 09:34
  • i saw this one but it does'n help because i tried the suggested solutions it's not solve the problem or not under the constraints. i make my question clear "The exacly question is: How do i fire Bind() on the Main Thread since the callback function fire on the new delegate thread." the question is also to learn not just the specific solution – shdr Jun 18 '18 at 09:58

1 Answers1

3

Your AsyncResult will have an AsyncState that holds a reference to your DataGridView. So you can use that control to check whether a context switch is needed for Bind() and if yes, use the Invoke of the control to switch threads:

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();
    }
}
rene
  • 41,474
  • 78
  • 114
  • 152