-
Notifications
You must be signed in to change notification settings - Fork 3
7. Threading extension π§΅
Package: Extensions.Hosting.Wpf.Threading
This extension enables switching between the WPF Main UI Thread and background ThreadPool threads using Microsoft.VisualStudio.Threading. This is particularly useful when you need to perform UI operations from a background thread, such as showing a dialog during a network request.
Install-Package Extensions.Hosting.Wpf.Threading
Register the thread switching services in ConfigureServices:
private static void ConfigureServices(HostBuilderContext hostContext, IServiceCollection services)
{
services.AddWpf<App>();
services.AddThreadSwitching(); // <-- Add this line
}This registers two services:
-
JoinableTaskContextβ initialized with the WPF thread and itsSynchronizationContext -
JoinableTaskFactoryβ the factory used to switch threads
If you need the generic version (e.g., for specific TApplication resolution):
services.AddThreadSwitching<App>();Inject JoinableTaskFactory into any class that needs thread switching:
private readonly JoinableTaskFactory _joinableTaskFactory;
public MyService(JoinableTaskFactory joinableTaskFactory)
{
_joinableTaskFactory = joinableTaskFactory;
}private async Task SomeOperationAsync()
{
// Currently on a background thread...
// Switch to the Main UI thread
await _joinableTaskFactory.SwitchToMainThreadAsync();
// Now on the UI thread β safe to manipulate UI elements
myWindow.Show();
}private async Task SomeOperationAsync()
{
// Currently on the UI thread...
// Switch to a threadpool thread
await TaskScheduler.Default;
// Now on a background thread β do heavy computation
var result = await DoExpensiveWorkAsync();
// Switch back to UI thread to show results
await _joinableTaskFactory.SwitchToMainThreadAsync();
DisplayResult(result);
}private readonly JoinableTaskFactory _joinableTaskFactory;
public SomeViewModel(JoinableTaskFactory joinableTaskFactory)
{
_joinableTaskFactory = joinableTaskFactory;
}
private async Task LoadDataAsync()
{
// On the caller's thread
await DoAsync();
// Explicitly switch to a threadpool thread
await TaskScheduler.Default;
// Do background work
var data = await FetchDataFromApiAsync();
// Switch to the Main thread to update UI-bound properties
await _joinableTaskFactory.SwitchToMainThreadAsync();
Items = data;
}When you call AddThreadSwitching(), the library:
- Retrieves the
IWpfThreadservice (which holds the WPF thread reference and itsSynchronizationContext) - Creates a
JoinableTaskContextinitialized with the WPF main thread and synchronization context - Registers
JoinableTaskFactoryas a singleton
This ensures that SwitchToMainThreadAsync() correctly targets the WPF dispatcher thread.
For advanced use cases (deadlock avoidance, nested joins, etc.), see the Microsoft.VisualStudio.Threading repository.
Microsoft.Extensions.Hosting.Wpf
Getting Started
Core Features
Extensions
Reference