Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF exe running very slow compared to running in Visual studio

I have created an application in WPF using the MVVM pattern.

The application is running fine in the Visual Studio debugger, but when I'm running the exe from the debug/release folder, it becomes very slow.

Here is my RelayCommand class:

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;
    }
}

If I remove the CanExcecute() method from my RelayCommand class, then the exe version runs as normal.

Please can anyone explain why this thing is happening? Is it for the CanExecuteChanged event handler?

like image 730
sushmitgos Avatar asked Oct 18 '22 21:10

sushmitgos


1 Answers

You have two options:

  1. Don't use the CommandManager.RequerySuggested event.

The current implementation of the CommandManager enqueues a requery of all commands as a Dispatcher action with a DispatcherPriority.Background. That means, whenever your application is idle, the CommandManager will call the CanExecute() methods of all commands you have registered in the CommandManager. If any of this methods does consume some resources (like using a Database or reading a File), then you will probably notice the overall performance drop of your application.

E.g. Prism has its own implementation of the ICommand without subscribing to the CommandManager's event. This works great too, but you have to call the RaiseCanExecuteChanged() methods explicitly when you want to update the command state. This is normally not a problem, since you should be interested only in a few of commands at one time, not in all the commands in your application.

  1. Don't use any heavy-weight tasks in your CanExecute() methods.

They should be like this, short and fast:

public bool CanExecute()
{
    return this.isIdle && this.someFlag && !this.CommandAbort.CanExecute();
}
like image 144
dymanoid Avatar answered Nov 15 '22 07:11

dymanoid