Invoking WPF Dispatcher with anonymous method
Asked Answered
D

4

9

I just realized in a C# .Net 4.0 WPF background thread that this doesn't work (compiler error):

Dispatcher.Invoke(DispatcherPriority.Normal, delegate()
{
    // do stuff to UI
});

From some examples I found out that it had to be casted like this: (Action)delegate(). However, in other examples it is casted to other classes, e.g. System.Windows.Forms.MethodInvoker.

Can anybody tell me what exactly is wrong with the example above? I also tried to reproduce it with other methods, but it was always working without casting:

delegate void MyAction();
void Method1(MyAction a) {
    // do stuff
}

void Method2(Action a) {
    // do stuff
}

void Tests()
{
    Method1(delegate()
    {
        // works
    });

    Method2(delegate()
    {
        // works
    });

    Method1(() =>
    { 
        // works
    });

    Method2(() =>
    {
        // works
    });

    Method2(new Action(delegate()
    {
        // works
    }));

    new System.Threading.Thread(delegate()
    {
        // works
    }).Start();
}

So whats the best (most elegant, less redundant) way to invoke the Dispatcher, and whats so special with it that delegates must be casted?

Dam answered 5/6, 2011 at 20:45 Comment(0)
S
12

Look at the signature for Dispatcher.Invoke(). It doesn't take Action or some other specific delegate type. It takes Delegate, which is the common ancestor of all delegate types. But you can't convert anonymous method to this base type directly, you can convert it only to some specific delegate type. (The same applies to lambdas and method groups.)

Why does it take Delegate? Because you can pass to it delegates that take parameters or have return values.

The cleanest way is probably:

Action action = delegate()
{
    // do stuff to UI
};

Dispatcher.Invoke(DispatcherPriority.Normal, action);
Shod answered 5/6, 2011 at 20:54 Comment(1)
You can use a method group, e.g. Action action = MyMethod;Parks
J
21

I would like to point out even more cleaner code example to Svick's one, after all we all like one liners don't we?

Dispatcher.Invoke((Action) delegate { /* your method here */ });
Joli answered 9/2, 2013 at 21:2 Comment(3)
This is really a comment, not an answer. It lacks all of the explanation the question is asking for.Kill
Servy: Yes, I totally missed the sentence where the fellow asking this question actually answers his own question.. sorry :(Joli
+1 - I partially disagree with Servy. Jaska, please edit your answer so it's confidently saying: this is the cleanest way to involve anonymous method. Your answer is exactly answering the question title: "Invoking WPF Dispatcher with anonymous method." - Thank, you for that.Jena
S
12

Look at the signature for Dispatcher.Invoke(). It doesn't take Action or some other specific delegate type. It takes Delegate, which is the common ancestor of all delegate types. But you can't convert anonymous method to this base type directly, you can convert it only to some specific delegate type. (The same applies to lambdas and method groups.)

Why does it take Delegate? Because you can pass to it delegates that take parameters or have return values.

The cleanest way is probably:

Action action = delegate()
{
    // do stuff to UI
};

Dispatcher.Invoke(DispatcherPriority.Normal, action);
Shod answered 5/6, 2011 at 20:54 Comment(1)
You can use a method group, e.g. Action action = MyMethod;Parks
G
1

I use this one:

Dispatcher.Invoke((Action)(() => YourCodeHere()));

Gravimeter answered 20/9, 2018 at 8:51 Comment(0)
L
0

The 'Delegate' class is abstract so you have to provide the compiler with a type that is derived from it. Any class derived from Delegate will do but Action is usually the most appropriate one.

Literalminded answered 5/6, 2011 at 20:58 Comment(7)
Yes, but delegate {} looks like it already is of type that is derived from Delegate, so your answer doesn't explain why is the cast necessary.Shod
delegate (lowercase) is a c# keyword, not a class. This is a very common confusion.Literalminded
@Robert, I wasn't talking about some type delagate (you're right that such type doesn't exists), I was talking about the expression delegate { }, which declares an anonymous method, so it makes sense to think that expression can be converted implicitly to Delegate.Shod
@Shod yes, but the question that the compiler infer is what type of delegate your method should be. it can't be of type Delegate because that is abstract. the compiler could probably be given some smarts to create an anonymous subclass of Delegate based on your parameter and return types (if any) and then cast to that on your behalf... but as of .NET 4, they haven't done so. maybe next time?Literalminded
@Robert, yes that was my point and I think it's not obvious from your answer.Shod
So what exactly does the delegate { } expression return then? It looks like the compiler says to me: Here you got an object from an abstract type, but you must not use it like that, because objects of abstract types are not allowed. Cast it to something legal and we will forget that this happened.. :) (metaphorically speaking)Dam
@doug yeah basically. Tho in some cases the compiler is smart enough to infer the type like when you do += on an eventLiteralminded

© 2022 - 2024 — McMap. All rights reserved.