0

I'm trying to run code from worker threads by invoking it on the main UI thread; however, I don't have an instance of the main form or any controls (nor do I want one in the class where the threaded code is running).

I've found things like the built-in System.Windows.Forms.MethodInvoker delegate, which has an Invoke() method. I figured if I instantiated my MethodInvoker on the main thread and then called its Invoke() method on the worker thread, everything would work as I wanted. However, simple debugging demonstrates that the invoked method still runs on the worker thread.

I can't find any documentation on MethodInvoker.Invoke(). There isn't even a "Members" link on MSDN for it, yet it exists. The only thing I've found, which states what I already know, is the accepted answer in this SO post:

Using C# MethodInvoker.Invoke() for a GUI app... is this good?

So, my questions are:

  1. How can I invoke a method on the main thread without an instance of the main form or other UI elements?

  2. Why isn't the MethodInvoker.Invoke() method documented anywhere? What am I missing?

Community
  • 1
  • 1
rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • You could pass the invoke method to the code running the thread during startup so that you could call it. Normally, when I have information that the UI needs from a background thread, I send a notification event that some part of the UI is listening for and then have the event handler call the invoke. Can you explain more if this isn't viable for your code? – Steve Mitcham May 22 '14 at 13:28
  • MethodInvoker is a delegate, which means that it defines a function signature, but no behavior. It is what is passed into the Invoke method on the class (in this case, your UI form) – Steve Mitcham May 22 '14 at 13:32
  • @SteveMitcham -- Thanks. I have a class with a timer that is in charge of updating multiple UI elements when the timer elapses. This class doesn't actually hold references to these UI elements; rather, it holds references to their "code behinds" (I'm separating the presentation from the logic). I don't want to store any UI elements nor have my timer class know anything about the UI. – rory.ap May 22 '14 at 13:38
  • @SteveMitcham -- I like your suggestion about using event handlers in the UI. – rory.ap May 22 '14 at 13:39

2 Answers2

1

Why isn't the MethodInvoker.Invoke() method documented anywhere? What am I missing?

It's documented. It's generated by C# compiler for each declared System.Delegate together with BeginInvoke()/EndInvoke(). You seldom (or never) will have to call it directly because you simply can use function-style invocation:

MethodInvoker func = ...
func(this, EventArgs.Empty);

Moreover please note that MethodInvoker is just a delegate not a class to dispatch calls to other threads. What does this mean? That if you invoke it then it will be called in the caller thread.

How can I invoke a method on the main thread without an instance of the main form or other UI elements?

Simply you can't. Fortunately you can access System.Windows.Forms.Application.OpenForms list. Pick first open form and use it to dispatch your call to UI thread.

if (Application.OpenForms.Count > 0)
    Application.OpenForms.BeginInvoke(...);
else
    // Ooops, no UI? You may invoke directly
Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
1

When creating the class that will run off thread. Create an event that can pass notification data out that the UI objects can hook to, then the UI can call invoke as necessary.

class MyBackgroundWorker
{
   public event EventHandler<MyArgs> Progress;

   public void Start()
   {
        Task.Factory.StartNew(() => {
          while(shouldBeDoingStuff) {
             ...  stuff to be done ...
             if (Progress) 
             {
                Progress(myArgs);
             }
          }
        });
   }

meanwhile on the UI form that kicks things off:

   var task = new MyBackgroundWorker();
   task.Progress += (myArgs) => {
       Invoke(()=> HandleEvent(myArgs));
   }

That's a bit rough, there are other answers on SO for best practices in calling the invocation.

Steve Mitcham
  • 5,268
  • 1
  • 28
  • 56