【问题标题】:How do you call a method from a UI thread?如何从 UI 线程调用方法?
【发布时间】:2020-04-24 00:45:55
【问题描述】:

我正在尝试从多线程程序访问 Microsoft Store。该程序本身运行良好 - 没有问题,但方法

Windows.Foundation.IAsyncOperation<StorePurchaseResult> purchase = product.RequestPurchaseAsync();

抛出异常:

"窗口句柄无效。\r\n\r\n此函数必须从 UI 调用 线程”

我的代码如下...

        private void testButton_Click(object sender, EventArgs e)
        {
            //Dispatcher dispUI = Dispatcher.CurrentDispatcher;
            //dispUI.BeginInvoke((ThreadStart)delegate ()
            //{
            //    _ = SetStore();
            //});

            //Dispatcher.BeginInvoke(new Action(TestStuff));


            _ = SetStore();

        }

        [ComImport]
        [Guid("4AEEEC08-7C92-4456-A0D6-1B675C7AC005")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IInitializeWithWindow
        {
            void Initialize(IntPtr hwnd);
        }


        private async Task SetStore()
        {
            try
            {
                StoreContext theStore = StoreContext.GetDefault();

                // "Unable to cast object of type 'Windows.Services.Store.StoreContext' to type 'IInitializeWithWindow'."
                // IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)theStore;
                // initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);

                StoreProductResult app = await theStore.GetStoreProductForCurrentAppAsync();

                // This works...
                StoreProduct product = app.Product;
                string title = product.Title;
                string price = product.Price.FormattedPrice;

                // This works...
                StoreAppLicense license = await theStore.GetAppLicenseAsync();
                bool trial = license.IsTrial;
                bool full = license.IsActive;

                // "Invalid window handle.\r\n\r\nThis function must be called from a UI thread" 
                StorePurchaseResult result = await theStore.RequestPurchaseAsync("9NRFBVGVGW8K");


                // "Invalid window handle.\r\n\r\nThis function must be called from a UI thread" 
                // Windows.Foundation.IAsyncOperation<StorePurchaseResult> purchase = product.RequestPurchaseAsync();
            }
            catch (Exception e)
            {
                int a = 1;
            }

        }

我已将 VS2019 UWP 安装程序项目与商店相关联,我认为这就是为什么其他方法无需使用 IInitializeWithWindow 强制转换商店对象即可返回正确答案的原因(这也会引发错误,但绕过似乎让代码工作)。

我想我必须以某种方式进入 UI 线程 - 不知道怎么做。来自各地的各种例子似乎对我不起作用。谁能帮帮我?

编辑:这是一个带有 UWP 包装器的 .Net 程序,用于创建 MSIX 包。

【问题讨论】:

  • 我不得不删除我的答案,因为它适用于 UWP 应用程序。也许澄清您的应用程序的类型(例如 WPF、WinForm)。
  • 我对这个答案有了更进一步的了解。很高兴在你删除它之前我得到了它。现在收到“在意外时间调用了一个方法。\r\n\r\n无法创建新视图,因为尚未创建主窗口”。
  • 那是因为 UWP 中的CoreWindow.MainView 没有被激活。但这是 UWP 的事情,可能不适用于您的非 UWP 应用 :)
  • 哦,好的。无论如何,谢谢!

标签: c# ui-thread


【解决方案1】:

对于 UWP,您需要使用以下代码调用 UI 线程:

await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
    //UI code here
});

【讨论】:

  • 感谢您的回答。我已经澄清了我的问题——我的程序是带有 UWP 包装器的 .NET。这个 sn-p 返回一个不同的错误,显然是因为它不是 UWP。
【解决方案2】:

尝试关注,它适用于 .net 6 wpf 应用程序

WinRT.Interop.InitializeWithWindow.Initialize(storeContext, new WindowInteropHelper(window).Handle);

【讨论】:

  • 对于 WPF Application.Current.Dispatcher.Invoke 会简单得多
猜你喜欢
  • 2012-12-15
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
相关资源
最近更新 更多