MAUI中启动DeviceWatcher时报"A method was called at an unexpected time"错误的解决方法咨询
Great job getting your HID communication service up and running via DI in MAUI—those platform-specific workarounds can be tricky! Let's tackle that DeviceWatcher error you're seeing.
The root of this issue lies in the thread model differences between MAUI (specifically the Windows platform) and WPF. In WPF, the Dispatcher handles UI thread context automatically in many cases, but MAUI's Windows implementation requires explicit care to ensure you're calling DeviceWatcher.Start() within the correct UI thread context.
Here are the steps to resolve this:
1. Execute DeviceWatcher.Start() in the UI Thread Context
MAUI's Windows platform relies on the CoreDispatcher (from Windows.UI.Core) to manage UI thread operations. You need to wrap the Start() call in a dispatch to ensure it runs on the correct thread.
Option 1: Use MAUI's IDispatcher (Cross-Platform Friendly)
Inject MAUI's IDispatcher into your HidCommunicationService and use it to dispatch the start operation:
using Microsoft.Maui.Dispatching; public class HidCommunicationService : IHidCommunicationService { private readonly IDispatcher _dispatcher; private DeviceWatcher _deviceWatcher; public HidCommunicationService(IDispatcher dispatcher) { _dispatcher = dispatcher; } public async Task StartDeviceMonitoring(ushort usagePage, ushort usageId, ushort vendorId, ushort productId) { // Clean up existing watcher if needed _deviceWatcher?.Stop(); _deviceWatcher?.Dispose(); string aqsFilter = HidDevice.GetDeviceSelector(usagePage, usageId, vendorId, productId); _deviceWatcher = DeviceInformation.CreateWatcher(aqsFilter); // Register your device event handlers here (Added, Removed, Updated) _deviceWatcher.Added += DeviceWatcher_Added; _deviceWatcher.Removed += DeviceWatcher_Removed; _deviceWatcher.Updated += DeviceWatcher_Updated; // Dispatch the Start() call to the UI thread await _dispatcher.DispatchAsync(() => { _deviceWatcher.Start(); }); } // Implement your event handlers here private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args) { // If updating UI, dispatch back to UI thread here too _dispatcher.Dispatch(() => { // Handle device update }); } // Don't forget to clean up the watcher when done public void StopDeviceMonitoring() { _dispatcher.Dispatch(() => { _deviceWatcher?.Stop(); _deviceWatcher?.Dispose(); _deviceWatcher = null; }); } }
Option 2: Windows-Specific CoreDispatcher Call
If you prefer a platform-specific approach (since this issue is Windows-only), you can directly use the Windows CoreDispatcher:
#if WINDOWS using Windows.UI.Core; // Inside your Start method await CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { _deviceWatcher.Start(); }); #endif
2. Avoid Starting the Watcher in the Service Constructor
Another common pitfall is trying to start the DeviceWatcher too early (like in the service's constructor). At that point, the UI thread context may not be fully initialized. Instead, call your StartDeviceMonitoring method after your app has fully loaded—for example, in a page's OnAppearing event or after your main window has initialized.
3. Ensure Proper Cleanup
Always stop and dispose of the DeviceWatcher when you're done with it (e.g., when navigating away from a page or shutting down the service) to prevent memory leaks and unexpected behavior.
This should resolve the "A method was called at an unexpected time" error, as you're now ensuring the DeviceWatcher starts in the correct UI thread context required by MAUI's Windows platform.
内容的提问来源于stack exchange,提问作者Artur Wyszomirski

