使用匿名方法调用WPF调度程序

9

我刚刚意识到,在C# .Net 4.0 WPF背景线程中,这个方法不起作用(编译器错误):

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

我发现一些示例需要这样进行强制转换:(Action)delegate()。然而,在其他示例中,它被强制转换为其他类,例如System.Windows.Forms.MethodInvoker
有人能告诉我上面的示例到底有什么问题吗?我还尝试使用其他方法进行复制,但总是可以在没有强制转换的情况下工作。
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();
}

那么调用Dispatcher最佳的方法是什么(最优雅、最少冗余),为什么委托必须要转换类型才能使用它?
4个回答

21

我想指出更加简洁的代码示例,以补充Svick所提供的示例。毕竟,我们都喜欢一行代码解决问题,不是吗?

Dispatcher.Invoke((Action) delegate { /* your method here */ });

1
这只是一条评论,而不是答案。它缺乏问题所要求的所有解释。 - Servy
Servy:是的,我完全忽略了这个问题提问者实际上回答了自己的问题的那句话..抱歉 :( - Jaska
3
+1 - 我在某种程度上不同意Servy的观点。Jaska,请编辑你的回答,使其自信地表达:这是涉及匿名方法的最简洁方式。你的回答正好回答了问题标题:“使用匿名方法调用WPF Dispatcher。”- 谢谢。 - Max

12

看一下 Dispatcher.Invoke() 的签名。它不需要 Action 或其他特定的委托类型,而是需要 Delegate,这是所有委托类型的共同祖先。但你不能直接将匿名方法转换为这个基础类型,你只能将其转换为某个特定的委托类型。(lambda 表达式和方法组也是如此。)

为什么要使用 Delegate?因为你可以传递带参数或有返回值的委托。

最简洁的方式可能是:

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

Dispatcher.Invoke(DispatcherPriority.Normal, action);

你可以使用方法组,例如 Action action = MyMethod; - Stealth Rabbi

1
我使用这个:
Dispatcher.Invoke((Action)(() => YourCodeHere()));

0

'Delegate'类是抽象的,因此您必须提供编译器一个派生自它的类型。任何从Delegate派生的类都可以,但Action通常是最合适的。


是的,但是 delegate {} 看起来 已经是从 Delegate 派生的类型,所以你的回答并没有解释为什么需要进行强制转换。 - svick
delegate(小写)是C#的关键字,而不是类。这是一个非常常见的混淆。 - Robert Levy
@Robert,我不是在谈论某种类型的“delagate”(你说得对,这样的类型不存在),我是在谈论表达式“delegate { }”,它声明了一个匿名方法,因此可以想象这个表达式可以隐式转换为“Delegate”。 - svick
@svick 是的,但编译器推断出的问题是你的方法应该是什么类型的委托。它不能是Delegate类型,因为那是抽象的。编译器可能可以被赋予一些智能来创建一个基于你的参数和返回类型(如果有的话)的匿名Delegate子类,然后代表你进行强制转换...但截至.NET 4,他们还没有这样做。也许下次会呢? - Robert Levy
@doug 是的,基本上是这样。但在某些情况下,编译器足够聪明,可以推断出类型,例如当您在事件上执行 += 操作时。 - Robert Levy
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接