Есть ли влияние CanExecuteCommand на производительность?

Каковы последствия использования CanExecuteCommand объекта ICommand для производительности. Выполняется ли метод снова и снова?

Мне нужно перебрать коллекцию из примерно 200 объектов, на основе которых было принято решение о том, следует ли активировать кнопку, связанную с командой? Выполняется ли CanExecuteCommand повторно, что замедляет работу моего приложения?


person ganeshran    schedule 07.09.2011    source источник
comment
Да, но только если вы не оптимизируете преждевременно.   -  person    schedule 07.09.2011
comment
Будет ли ваш комментарий немного двусмысленным.   -  person Kyeotic    schedule 07.09.2011
comment
Уилл, я тоже не совсем понимаю. Моя проверка — это итерация около 200 объектов — древовидное представление. Он просто проверяет простое свойство и не требует много времени при однократном запуске. Меня беспокоит, если CanExecute многократно запускается, замедляя код. Может кто-нибудь, пожалуйста, пролить немного света   -  person ganeshran    schedule 07.09.2011
comment
Уилл говорит следующее: Ваш код в CanExecute не должен делать слишком много, потому что его действительно можно вызывать часто. Но вам не следует беспокоиться об этом только в том случае, если это ДЕЙСТВИТЕЛЬНО замедляет работу вашей программы, то есть если вы можете измерить ухудшение производительности из-за слишком большого количества вызовов CanExecute.   -  person Daniel Hilgarth    schedule 07.09.2011


Ответы (2)


Интерфейс ICommand выглядит следующим образом:

public interface ICommand
{
    // two methods
    bool CanExecute(object parameter);
    void Execute(object parameter);

    // one event
    event EventHandler CanExecuteChanged;
}

Событие CanExecuteChanged следует вызывать в любое время, когда вы хотите указать, что метод CanExecute должен быть проверен/вызван WPF. Тот, кто реализует ICommand, должен вызвать событие, и тот, кому нужно обновить состояние включения кнопки в графическом интерфейсе (система WPF), должен зарегистрироваться и обработать событие, и оно вызывает CanExecute.

В классе RelayCommand Джоша Смита он использует встроенный класс CommandManager WPF для повышения CanExecuteChanged:

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

По сути, CommandManager в WPF — это синглтон, который прослушивает все виды маршрутизируемых событий: KeyUpEvent, MouseUpEvent и т. д., а затем сообщает всем «привет, произошло что-то интересное», вызывая свое событие RequerySuggested. Поэтому, если вы используете RelayCommand, ваш CanExecute будет вызываться каждый раз, когда CommandManager думает, что в графическом интерфейсе произошло что-то интересное (даже если это не имеет ничего общего с вашей коллекцией). Если у вас есть 50 команд, каждый раз, когда вы нажимаете клавишу, он перепроверяет все 50 команд. Так что да, это может быть проблемой производительности. Однако, если ваша логика в вашем методе CanExecute действительно проста, это, вероятно, не проблема. Вывод: не делайте вызовы API базы данных или сети в методе CanExecute.

Альтернативой использованию CommandManager.RequerySuggested для создания события ICommand.CanExecuteChanged является использование собственной версии RelayCommand, в которой вы выполняете свою собственную проверку и создаете CanExecuteChanged вручную, или смотрите на класс DelegateCommand среды Prism, где они не связаны с CommandManager, и вы необходимо вручную вызвать событие CanExecuteChanged, что вы, вероятно, могли бы сделать, создав прослушиватель для PropertyChanged, а затем подняв CanExecuteChanged по команде.

Однако я согласен с @Will выше. RelayCommand, вероятно, будет работать более 80% времени без проблем. Если вы начинаете обнаруживать проблемы с производительностью, вы можете создать свою собственную версию RelayCommand или использовать Prism DelegateCommand и поднять CanExecuteChanged вручную.

person Kendrick    schedule 07.09.2011
comment
Связанный ответ здесь: stackoverflow.com/questions/6634777/ - person Kendrick; 07.09.2011
comment
Спасибо, Кендрик и Уилл, ваши ответы подытожили меня. Я поставлю его в CanExecute и поищу любые задержки в производительности. Если найду, то посмотрю другие реализации - person ganeshran; 07.09.2011

Для будущих пользователей Google: я создал несколько другую реализацию команды. Во-первых, он привязан к событию OnPropertyChanged класса ViewModelBase, но также позволяет модели представления инициировать событие CanExecuteChanged для всех экземпляров Command внутри нее, независимо от изменения свойства, например, в случае One Way. Сценарий привязки к источнику. это решение является частью сборки PerrypheralFrameowrk.WPF, доступной в nuget и codeplex. Поищи это. Вики codeplex имеет подробную документацию, как и классы в сборке.

person Eyal Perry    schedule 01.11.2014