【问题标题】:Dispatcher BeginInvoke Syntax调度程序 BeginInvoke 语法
【发布时间】:2010-09-21 13:31:11
【问题描述】:

我一直在尝试遵循一些 WCF 数据服务示例并拥有以下代码:

private void OnSaveCompleted(IAsyncResult result)
    {
        Dispatcher.BeginInvoke(() =>
        {
            context.EndSaveChanges(result);
        });
    }

由以下调用:

this.context.BeginSaveChanges(SaveChangesOptions.Batch, this.OnSaveCompleted, null);

现在我有点困惑了。首先,代码的第一位显示语法错误

参数类型 lambda 表达式不可分配给参数类型 System.Delegate

因此,我没有盲目地尝试遵循示例代码,而是尝试了解这里发生了什么。不幸的是,我很难理解错误以及实际发生的情况。谁能解释一下?

我觉得有点傻,因为我确信这很容易。

【问题讨论】:

    标签: c# .net multithreading wcf-data-services


    【解决方案1】:

    问题在于编译器不知道您尝试将 lambda 表达式转换为哪种委托。您可以使用强制转换或单独的变量来修复它:

    private void OnSaveCompleted(IAsyncResult result)
    {        
        Dispatcher.BeginInvoke((Action) (() =>
        {
            context.EndSaveChanges(result);
        }));
    }
    

    private void OnSaveCompleted(IAsyncResult result)
    {
        Action action = () =>
        {
            context.EndSaveChanges(result);
        };
        Dispatcher.BeginInvoke(action);
    }
    

    【讨论】:

    • 谢谢,但现在我收到“无法在静态上下文中访问非静态方法 'BeginInvoke'。我现在更困惑了,因为这不是静态方法?
    • @Jon:它认为您正在尝试使用 BeginInvoke 作为 Dispatcher 类的静态方法 - 而您想使用 Dispatcher property 然后调用 BeginInvoke相关实例。我的猜测是,这不在具有 Dispatcher 属性的适当类中。刚刚看到这是 WCF,我不确定您会从哪里获得 Dispatcher。我更习惯在 WPF 和 Silverlight 中使用它。
    • 这实际上是在 WPF 应用程序中的 ViewModel 类上
    • ViewModel 通常不知道视图,更不用说关联的调度程序了。你可以继续使用 Dispatcher.CurrentDispatcher,但我强烈建议不要这样做(你很容易进入错误的线程,并且永远不会调用委托);我认为最好的方法是使用类似 MVVMLight 的 Messenger 并向视图发送消息 - 消息可以包含操作,视图可以使用其调度程序调用它。
    • @Jon:绝对值得更新问题以反映这一点。 WCF 部分无关紧要,但 WPF 部分高度相关。至于让调度程序到 ViewModel - 您可以按照 Alex 的建议使用信使,或者您可以将 Dispatcher nito 注入 ViewModel ......不是作为调度程序,而是就围绕它的包装而言,实现您自己的界面。这样你就可以测试你在线程安全方面做的事情是正确的。我以前做过,效果很好。
    【解决方案2】:

    Jon Skeet 的回答非常好,但还有其他可能性。我更喜欢“开始调用新操作”,它对我来说易于阅读和记住。

    private void OnSaveCompleted(IAsyncResult result)
    {       
        Dispatcher.BeginInvoke(new Action(() =>
        {
            context.EndSaveChanges(result);
        }));
    }
    

    private void OnSaveCompleted(IAsyncResult result)
    {       
        Dispatcher.BeginInvoke(new Action(delegate
        {
            context.EndSaveChanges(result);
        }));
    }
    

    private void OnSaveCompleted(IAsyncResult result)
    {       
        Dispatcher.BeginInvoke(new Action(() => context.EndSaveChanges(result)));
    }
    

    【讨论】:

    • 与只做(动作)演员相比,做一个“新动作”的成本可能更高?
    【解决方案3】:

    如果你的方法不需要参数,这是我找到的最短的版本

    Application.Current.Dispatcher.BeginInvoke((Action)MethodName); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 2012-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多