windowsgm
windowsgm

Reputation: 1616

Multithreading Calling a Delegate

To quote Marc Gravell:

///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
    someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files

I'm looking to do this with WPF so can't use the invoke method. Any thoughts? This Threading stuff is doing my head in :/

MORE DETAIL

I began my new Thread like so

Thread t = new Thread (LoopThread);
t.Start();
t.Join();

But throughout LoopThread, I want to write to the UI.

UPDATE

Thanks to Jon Skeet for the Dispatcher.Invoke bit. Seems MethodInvoker is WinForms also. WPF equivalent?

UPDATE 2

Thanks Adriano for suggesting instead of System.Windows.Forms.MethodInvoker, using System.Action.

(You guys were right about the this parameter confusion, just need to build to remove errors.)

Bus since adding the SimpleInvoke, now I'm hit with

Extension method must be defined in a non-generic static class

on the line

public partial class MainWindow : Window

Any thoughts?

Upvotes: 1

Views: 331

Answers (3)

sergeyxzc
sergeyxzc

Reputation: 615

as compromise using SynchronizationContext:

    // gui thread

    var sc = SynchronizationContext.Current;

// work thread

    sc.Post(s => 
    {
    someLabel.Text = newText
    }, null);

Upvotes: 0

s_nair
s_nair

Reputation: 812

Continuing from Jon Skeet comment, and you can call your extension like below

DispatcherObject.SimpleInvoke(() => someLabel.Text = newText);

Upvotes: -1

Jon Skeet
Jon Skeet

Reputation: 1500345

In WPF, you just use Dispatcher.Invoke instead of Control.Invoke.

The DispatcherObject class (which WPF classes derive from) exposes a Dispatcher property, so you just need:

Dispatcher.Invoke((Action) delegate {
    someLabel.Text = newText; // runs on UI thread
});

If you're using C# 3 or higher (and .NET 3.5 or higher) you might want to add an extension method to DispatcherObject:

// Make this a new top-level class
public static class DispatcherObjectExtensions
{
    public static void SimpleInvoke(this DispatcherObject dispatcherObject,
                                    Action action)
    {
        dispatcherObject.Dispatcher.Invoke(action);
    }
}

So you can just use:

// From within your UI code
this.SimpleInvoke(() => someLabel.Text = newText);

Upvotes: 6

Related Questions