在 WinForms 经典桌面应用程序中获取 CoreDispatcher

Getting CoreDispatcher in WinForms Classic Desktop app

我有一个 C# WinForms 应用程序可以在后台线程上扫描蓝牙设备。当需要连接到设备时,它必须调用以下方法,该方法必须在 UI 线程上调用:

 var btDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);

我知道你这样做的方法是将上面的内容封装在一个像 ConnectToBluetoothDevice 这样的异步方法中并像这样调用它:

dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => ConnectToBTDevice(args));

到目前为止一切顺利。 我的问题是我无法获得对 CoreDispatcher 实例的引用,因此我可以进行上述调用。我尝试了很多方法:

  1. 重复调用:

    try
    {
      dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
    
    }
    catch (System.InvalidOperationException e)
    {
      Console.WriteLine("Cannot get dispatcher yet");
    }
    

    在启动应用程序很久之后,上面的内容总是落入捕获块。

  2. 正在注册 Form.Shown 回调的回调,然后尝试从当前 UI 线程中获取调度程序的实例,如下所示:

    var form = new Form1();
    form.Shown += FormShown;
    Application.Run(form);
    
    ...
    
    private static void FormShown(Object sender, EventArgs e)
    {
        var window = CoreWindow.GetForCurrentThread();
        if (window != null)
        {
            dispatcher = window.Dispatcher;
        }
    }
    

    在这种情况下,window 始终为 null,这让我感到惊讶,因为此回调的全部意义在于它发生在显示表单 window 之后。这个回调不应该在 UI 线程和 return 它的 CoreWindow 上吗?

我在这里错过了什么?如何从 WinForms 应用程序获取 CoreDispatcher?

并非所有 UWP API 都可以从经典桌面应用程序访问。

您可以参考此 MSDN link,它解释了 只有 API 具有 DualApiPartition 属性可以从classic 桌面应用程序。

查看 CoreDispatcher 的文档,您会发现它 不支持 DualApiPartition 属性。

或者,classic 桌面应用程序可以引用 Dispatcher class,可以使用 System.Windows.Threading 命名空间通过 WindowsBase.dll 访问。