1

Is there a way to run code in UI thread while calling it outside of it? I know that it basically requires the use of control.Invoke or control.BeginInvoke. My problem is that i don't have access to UI elements to use those methods.

My situation is like this:

  1. UI - DataGridView with DataTable set as it's DataSource
  2. thread (BackgroundWorker) written outside of MainForm UI, that updates (adds rows) DataTable mentioned above

I've had problems with my app, so i've written a simple app with just the elements mentioned above, to check how it works (or rather why it doesn't) and I found that:

  1. when I update DataTable in my BackgroundWorker thread, DataGridview can't see this (probably all the events are fired from other thread), even calling DGV.Refresh() doesn't work (it updates DGV, but sometimes DGV gets broken and shows nothing or just 1 row), only forcing DGV refreshing with resizing, scrolling etc. forces DGV to show data from DataTable
  2. when I am able to run Invoke, everything works fine, nothing more to say

but this is just a simple app, where I have everything in a single file. what can i do with much greater app where my "other thread" can't see UI code? do I have to pass a single control as a parameter somehow, just to get access to that thread? or is there maybe some other, much better looking solution?

4
  • Separate the datasource and control from the UI and the BackgroundWorker. That way either of the 2 can access a common control. Look into IoC for ideas. You could use async/await as well, but from the sound of it, you don't have access to the UI code at all? So you are manipulating a 3rd party program? Commented Dec 18, 2014 at 9:07
  • 1
    How about using the ReportProgress method and the ProgressChanged event to actually update your UI? They are made for exactly that purpose. See msdn.microsoft.com/en-us/library/… for an example. Commented Dec 18, 2014 at 9:08
  • This can help you : WinForms multi-threaded databinding scenario, best practice? Commented Dec 18, 2014 at 9:11
  • I guess you are creating a new thread for update data from UI thread. You should be able to get the callback then do the UI update using control.BeginInvoke. And if you need better binding, use BindingSource. Commented Dec 18, 2014 at 9:18

2 Answers 2

7

you can use Application.OpenForms by this:

    public void DoSomething(string s)
    {
        var form = System.Windows.Forms.Application.OpenForms[0];
        if (form.InvokeRequired)
        {
            Action<string> m = DoSomething;
            form.Invoke(m, s);
            return;
        }

        //do something
    }
Sign up to request clarification or add additional context in comments.

1 Comment

work like charm ^_^ of course, maybe there are better solutions, but this one is all that I need for now, thanks
1

You could always use Application.OpenForms[0] to obtain a reference to the main form and thus have something to call Invoke on.

Also I'd say that your approach is not so smart. I'd create a new DataTable in the background worker and return it as the background worker's result.

Then, when the worker is finished (the RunWorkerCompleted event is called in the context of the UI thread), I'd merge the result records into the bound data table. This provides a clear separation of code that updates the UI and code that might even run headless.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.