WinRT 中 Dispatcher.invoke 的线程问题

本文关键字:线程 问题 invoke Dispatcher WinRT | 更新日期: 2023-09-27 18:31:48

我前段时间在MSDN论坛上发布了一个问题,涉及以下代码。它在新线程上创建,从文件中读取缩略图并通过调度程序显示它。

private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        Task.Factory.StartNew(async()=>{
            var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder; ;
            var file = await localFolder.CreateFileAsync(".txt", Windows.Storage.CreationCollisionOption.OpenIfExists);
            var t = await file.GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.DocumentsView);
            //Some proccessing....
            this.Dispatcher.Invoke(Windows.UI.Core.CoreDispatcherPriority.Normal,(a,b)=>{
                var bmp = new BitmapImage();
                bmp.SetSource(t); //Exception here
                image.Source = bmp;
            }, this, null);
            //Some more stuff...
        });
    }

图像只是 XAML 中的一个图像控件

如果执行上述代码,我会收到一个很大的异常。异常发生在 bmp.SetSource(t) 处。

以下是完整的异常信息:

转换为此运行时可调用包装器的 COM 上下文0x1347668失败,出现以下错误:无法进行传出呼叫,因为应用程序正在调度输入同步调用。(例外来自 HRESULT: 0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL))。这是通常是因为 COM 上下文0x1347668已创建的运行时可调用包装器已断开连接或繁忙执行其他操作,并且无法处理上下文转换。不代理将用于为 COM 组件上的请求提供服务,并且将直接调用 COM 组件。这可能会导致损坏或数据丢失。为避免此问题,请确保所有COM 上下文/单元/线程保持活动状态,可用于上下文转换,直到应用程序完全完成RuntimeCallableWrappers,表示存在的 COM 组件在他们里面。

从使用 Invoke 切换到 InvokeAsync 可以解决问题,但我想知道为什么。有人可以解释一下吗?

编辑:以上只是一些测试代码。我创建的任务旨在模拟在我的应用中发生的非 UI 线程上下文下的执行,因为它需要从非 UI 线程上下文读取文件和更新 UI。

WinRT 中 Dispatcher.invoke 的线程问题

我无法理解单击处理程序中Task的原因,因为无论如何您最终都会在 UI 线程上调用它。

private void Button_Click_1(object sender, RoutedEventArgs e)
{
  var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
  var file = await localFolder.CreateFileAsync(".txt", Windows.Storage.CreationCollisionOption.OpenIfExists);
  var t = await file.GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.DocumentsView);
  var bmp = new BitmapImage();
  bmp.SetSource(t); //Exception here
  image.Source = bmp;
}