WPF可执行文件运行速度比在Visual Studio中运行慢得多

5
我使用MVVM模式在WPF中创建了一个应用程序。
在Visual Studio调试器中,该应用程序运行良好。但是当我从debug/release文件夹中运行exe文件时,它变得非常缓慢。
这是我的RelayCommand类:
public class RelayCommand : ICommand
{
    private readonly Action<object> execute;
    private readonly Predicate<object> canExecute;

    public RelayCommand(Action<object> execute) : this(execute, DefaultCanExecute)
    {
    }

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged
    {
        add
        {
            CommandManager.RequerySuggested += value;
        }

        remove
        {
            CommandManager.RequerySuggested -= value;
        }
    }

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        bool res = false;
        if (canExecute != null)
        {
            res = canExecute(parameter);
        }

        return res;
    }

    public void Execute(object parameter)
    {
        execute(parameter);
    }

    private static bool DefaultCanExecute(object parameter)
    {
        return true;
    }
}

如果我从我的RelayCommand类中删除CanExcecute()方法,那么exe版本将像往常一样运行。
请问有人能解释这是为什么吗?这与CanExecuteChanged事件处理程序有关吗?

很难说,我们不知道您在CanExecute中运行的逻辑是什么。请创建一个[MCVE]。 - H H
@HenkHolterman 我正在检查数据库中的某些属性,我认为获取数据是问题所在。如果我只是从CanExcecute方法中返回true,那么程序就可以正常工作。 - sushmitgos
如果我只是遍历集合而不获取数据库,那么它就可以正常工作 :) - sushmitgos
数据库访问明显很慢,原因可能有一千个。你应该监控到对数据库的查询(例如,如果你使用SQL Server,则使用SQL Server Profiler),然后检查为什么要花这么长时间。关于“CommandManager.RequerySuggested”的答案也是正确的,它很糟糕。最后,可以用 return canExecute?.Invoke(parameter); 替换整个CanExecute方法。 - user1228
1个回答

3

您有两个选择:

  1. 不使用CommandManager.RequerySuggested事件。

CommandManager的当前实现将所有命令的重新查询排队为一个带有DispatcherPriority.BackgroundDispatcher操作。这意味着,每当您的应用程序处于空闲状态时,CommandManager将调用您在CommandManager中注册的所有命令的CanExecute()方法。如果其中任何一个方法消耗了一些资源(例如使用数据库或读取文件),那么您可能会注意到应用程序的整体性能下降。

例如,Prism具有自己的ICommand实现,而不订阅CommandManager的事件。这也非常好,但是当您想要更新命令状态时,必须显式调用RaiseCanExecuteChanged()方法。通常,这不是问题,因为您应该只对一些命令感兴趣,而不是您应用程序中的所有命令。

  1. 不要在CanExecute()方法中使用任何重量级任务。

它们应该像这样简短快速:

public bool CanExecute()
{
    return this.isIdle && this.someFlag && !this.CommandAbort.CanExecute();
}

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