ICommand.CanExecute async
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
ICommand.CanExecute is a synchronous method that returns bool, so it cannot itself be truly asynchronous. In MVVM applications, the correct pattern is to keep CanExecute fast, compute expensive state elsewhere, cache the result, and raise CanExecuteChanged when that cached result changes.
Why CanExecute Should Not Do Async Work
The WPF command system may call CanExecute frequently and at times you do not control. UI elements use it to decide whether buttons, menu items, and other command sources should be enabled.
Because the signature is:
there is nowhere to await naturally. If you try to block on asynchronous work inside CanExecute, you risk:
- freezing the UI thread
- causing deadlocks
- doing expensive work repeatedly
That is why CanExecute should behave like a quick state check, not like a network request or database query.
Use Cached State Plus CanExecuteChanged
The common design is:
- compute availability asynchronously elsewhere
- store the result in a field or property
- return that cached value from
CanExecute - raise
CanExecuteChangedwhen the value changes
Here is a simple async command implementation:
CanExecute stays synchronous and cheap, while the rest of the application can still update the allowed state asynchronously.
Perform the Expensive Check Outside CanExecute
Suppose whether a command can run depends on a server call. Do that work separately and then update the command.
This pattern is much safer than trying to turn CanExecute into an async method. The UI remains responsive, and the command system still gets a plain boolean when it asks.
A second benefit is predictability. The expensive check runs when you decide it should run, not whenever WPF happens to reevaluate commands.
Keep Execute Async-Aware Too
If Execute performs asynchronous work, make sure the command disables itself while running if re-entry should be prevented. That is why the example tracks _isRunning. Otherwise, the user may click repeatedly and start overlapping operations.
Some projects also define an IAsyncCommand interface that exposes Task ExecuteAsync(...) in addition to the ICommand members. That can make testing and composition easier, but the WPF binding surface still ultimately relies on synchronous CanExecute.
The practical split is clean: asynchronous work belongs in command execution and in background refresh logic, while the actual CanExecute answer stays as a cheap cached boolean for the binding system.
Common Pitfalls
- Trying to make
CanExecuteitselfasync, which does not fit theICommandcontract. - Blocking on async work inside
CanExecutewith.Resultor.Wait(). - Forgetting to raise
CanExecuteChangedafter the cached executable state changes. - Allowing multiple overlapping
Executecalls when the command should be single-run. - Recomputing availability on every UI query instead of deciding explicitly when the async check should run.
Summary
- '
ICommand.CanExecuteis synchronous and should remain fast.' - Do expensive checks asynchronously outside
CanExecute. - Cache the result and return that cached value from
CanExecute. - Raise
CanExecuteChangedwhenever the cached state changes. - Treat async command support as a coordination pattern around
ICommand, not as a differentCanExecutesignature.

