c# - 同步调用Async, 'marshalled for a different thread'消息

标签 c# windows-runtime async-await synchronous

我有一个 XAML 格式的 Windows 8 商店应用程序。我有一个绑定(bind)到属性的图像控件,但因为我要显示的 URL 需要身份验证,所以我必须创建一个 webresponse 并以这种方式生成位图,而不是仅仅为我的图像控件提供一个 URL。

问题是,内存流操作是异步的,对象的属性必须是同步的,而不是异步的。所以我有一个非常简单的设置:

public ImageSource ImageSource
{
    get { return Task.Run(() => BitmapImageUtils.ToImage(this.Upload.ThumbFile)).Result; }

并且 Image 控件具有 ImageSource 属性作为其绑定(bind)。问题是,我收到以下异常。 ListView 中有多个 Image 控件,它们都以这种方式绑定(bind),我的猜测是调用它的 UI 线程以某种方式将控制权移交给一个线程,然后尝试以某种方式返回。我对此有点陌生。

应用程序调用了为不同线程编码的接口(interface)。 (HRESULT 异常:0x8001010E (RPC_E_WRONG_THREAD))

感谢任何帮助。

--- 编辑 ToImage方法

public static async Task<BitmapImage> ToImage(byte[] byteArray)
    {
        var bitmapImage = new BitmapImage();

        var stream = new InMemoryRandomAccessStream();
        await stream.WriteAsync(byteArray.AsBuffer());
        stream.Seek(0);

        await bitmapImage.SetSourceAsync(stream);
        return bitmapImage;
    }

异常(注意异常是聚合异常的内部异常,我认为这是异步/等待异常的标准

at Windows.UI.Xaml.Media.Imaging.BitmapImage..ctor()
at Campfire.Utils.BitmapImageUtils.<ToImage>d__0.MoveNext()

最佳答案

核心问题是许多 UI 类型(包括 BitmapImage)具有 UI 线程关联,而您当前的代码试图在后台线程(Task.Run)上创建它们。

我建议您重新设计您的属性(property);你不应该让它阻塞 I/O 操作。我有一个 type在我的 AsyncEx library这允许您基本上数据绑定(bind)到 Task<T> 的结果.

您的属性(property)变成:

public INotifyTaskCompletion<ImageSource> ImageSource { get; private set; }

当您想开始下载时,您可以:

ImageSource = NotifyTaskCompletion.Create(BitmapImageUtils.ToImage(Upload.ThumbFile)));

然后您的数据绑定(bind)从 ImageSource 更改至 ImageSource.Result .还有其他属性(例如 ImageSource.IsFaultedImageSource.ErrorMessage)允许您使用数据绑定(bind)处理其他结果。注意 INotifyTaskCompletion<T>.Result 阻塞;它只会返回默认值,直到任务完成。

附言AggregateExceptionasync 中不正常/await .您看到它的唯一原因是因为您使用的是 Task<T>.Result ;如果你await同样的任务,你会得到一个包裹在AggregateException中的异常.

关于c# - 同步调用Async, 'marshalled for a different thread'消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20828690/

相关文章:

c# - 可以在 Winforms TextBox 上设置背景图像吗?

mocking - WinRT的模拟框架?

c# - XAML Designer 使用 VS2015 RTM 抛出拒绝访问异常

concurrency - Rust 异步等待 : check if any future in a list resolves to true concurrently?

javascript - MVC 上的成功/失败消息

c# - 存储库模式和多个相关的核心实体或业务对象——一个存储库还是多个?

windows-runtime - 处理后退按钮 Windows 8.1 通用应用程序

javascript - 带有 Async/Await 的 TypeScript 和 Promise 包装器。我如何绑定(bind)遗留代码?

javascript - 使用nodejs在异步函数中使用await和async的语法是什么?

c# - 如何从 JSON 中删除不需要的字符串属性