async Task.Run with MVVM
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
In MVVM (Model-View-ViewModel) applications, Task.Run offloads CPU-bound work to a background thread so the UI stays responsive. The key challenge is updating UI-bound properties from the background thread — WPF, UWP, and MAUI require property changes to be raised on the UI thread. Use async/await with Task.Run in your ViewModel commands, and the continuation after await automatically returns to the UI thread (when using the default SynchronizationContext).
Basic Pattern
After await Task.Run(...), execution resumes on the UI thread because WPF/MAUI captures the SynchronizationContext. This means you can safely update bound properties without explicit dispatching.
When to Use Task.Run
Task.Run adds thread pool overhead. For I/O-bound operations, the built-in async methods are more efficient because they do not consume a thread while waiting.
Async RelayCommand Implementation
This command disables itself while executing, preventing double-clicks from launching parallel operations.
Reporting Progress from Task.Run
Progress<T> captures the SynchronizationContext at construction time, so its callback always runs on the UI thread. Create it before entering Task.Run.
Cancellation Support
Pass the CancellationToken to Task.Run and check it periodically inside the delegate. This lets users cancel long-running operations via a Cancel button bound to CancelCommand.
Error Handling
Exceptions thrown inside Task.Run are captured by the Task and re-thrown at the await point. The catch block runs on the UI thread, so you can safely update error-display properties.
Thread Safety with ObservableCollection
Never modify an ObservableCollection from a background thread in WPF. Either batch the results and add them after await, or use Dispatcher.Invoke for incremental updates.
MVVM Toolkit (CommunityToolkit.Mvvm)
The [RelayCommand] source generator creates LoadDataCommand automatically, including async support with built-in CanExecute management.
Common Pitfalls
- Using Task.Run for I/O:
await Task.Run(() => httpClient.GetAsync(url))wastes a thread pool thread. Useawait httpClient.GetAsync(url)directly — I/O-bound async operations do not needTask.Run. - Updating UI properties inside Task.Run: Setting bound properties inside
Task.Run(() => { Status = "Done"; })raisesPropertyChangedon a background thread, which can crash or silently fail in WPF. Always update UI properties after theawait. - Fire-and-forget commands:
async void Execute()in commands swallows exceptions silently if not wrapped in try/catch. Always add error handling insideasync voidmethods. - Missing ConfigureAwait: In library code (not ViewModels), use
await Task.Run(...).ConfigureAwait(false)to avoid capturing the synchronization context unnecessarily. In ViewModels, the default behavior (capturing context) is what you want. - Blocking with .Result or .Wait(): Calling
Task.Run(...).Resultor.Wait()blocks the UI thread and can cause deadlocks. Always useawaitto consume async results in ViewModels.
Summary
- Use
Task.Runin MVVM ViewModels to offload CPU-bound work to a background thread - After
await Task.Run(...), execution returns to the UI thread — safe to update bound properties - Do not use
Task.Runfor I/O-bound work — use native async APIs instead - Use
Progress<T>for progress reporting from background threads - Use
CancellationTokenSourcefor cancellable operations - Never modify
ObservableCollectionfrom a background thread in WPF - Consider CommunityToolkit.Mvvm for source-generated async commands
Related reading
- Async tasks and Simple Injector Lifetime scopes
- Async TCPClient missing replies from server
- Async testing with Karma and Mocha
- Async Thread.CurrentThread.CurrentCulture in .net-4.6
- Async two-way communication with Windows Named Pipes .Net
- async void, await, and exceptions - why do exceptions thrown after ''await'' from the GUI thread require AsyncVoidMethodBuilder for marshaling?
- Async timeout downloading a large file using StreamingResponseBody on Spring Boot
- async trio way to solve Hettinger's example

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.