前一段时间我在MSDN forum上发布了一个问题,涉及以下代码。它在新线程上创建,从文件中读取缩略图并通过Dispatcher显示它。
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...
});
}
image 只是XAML中的一个Image控件
如果上面的代码执行,我会遇到很大的异常。例外情况发生在bmp.SetSource(t)
。
以下是完整的异常信息:
为此RuntimeCallableWrapper转换到COM上下文0x1347668 失败,出现以下错误:无法拨打电话 应用程序正在调度输入同步调用。 (例外 来自HRESULT:0x8001010D(RPC_E_CANTCALLOUT_ININPUTSYNCCALL))。这是 通常因为COM上下文0x1347668所在 创建的RuntimeCallableWrapper已断开连接或正忙 做其他事情,不能处理上下文过渡。没有 代理将用于服务COM组件上的请求 将直接调用COM组件。这可能会导致 腐败或数据丢失。为避免此问题,请确保全部 COM上下文/公寓/线程保持活跃,可用 上下文转换,直到应用程序完全完成 RuntimeCallableWrappers,表示生活的COM组件 他们内心。
从使用Invoke切换到InvokeAsync修复了问题,但我想知道为什么。有人可以解释一下吗?
编辑:上面只是一些测试代码。我创建的任务是为了模拟在我的应用程序中出现的非UI线程上下文中的执行,因为它需要从非UI线程上下文中读取文件和更新UI。
答案 0 :(得分:2)
我无法理解点击处理程序中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;
}