Invoking WPF Dispatcher with anonymous method

2019-02-21 15:54发布

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?

4条回答
Ridiculous、
2楼-- · 2019-02-21 16:31

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);
查看更多
在下西门庆
3楼-- · 2019-02-21 16:36

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 */ });
查看更多
老娘就宠你
4楼-- · 2019-02-21 16:47

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.

查看更多
小情绪 Triste *
5楼-- · 2019-02-21 16:47

I use this one:

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

查看更多
登录 后发表回答