线程无法访问该对象。

3

我声明了一个字段:

WriteableBitmap colorBitmap;

然后我创建了一个简单的线程来执行某些操作:

private void doSomething()
{
    // ... bla bla bla
    colorBitmap = new WriteableBitmap(/* parameters */);
    myImage.Source = colorBitmap; // error here:S
}

在Windows_Loaded事件中,我声明并启动了一个新线程:
private void window_Loaded(object sender, RoutedEventArgs e)
{
    Thread th = new Thread(new ThreadStart(doSomething));
    th.Start();
}

问题在于我无法更改myImage的源。我收到了以下错误:
InvalidOperationException未处理 因为不同的线程拥有它,所以调用线程无法访问该对象。
我尝试使用Dispatcher.Invoke,但没有帮助...
Application.Current.Dispatcher.Invoke((Action)delegate
{
    myImage.Source = colorBitmap;
});

我一直在寻找答案,但是从来没有找到和我的情况完全相同的案例。请问有人能帮我理解如何解决这类问题吗?(我最近也遇到了同样的问题,但我无法调用该方法,因为其他线程已经拥有它)。


2
从我个人的经验来看,这应该是WPF或Silverlight吧?如果我没记错的话(我很少会),你不能在后台线程上实例化一个新的WriteableBitmap(因为某些愚蠢的原因)。不确定为什么在将其分派到主线程后它仍然无法工作。也许可以尝试使用myImage.Dispatcher.Invoke而不是Application.Current.Dispatcher.Invoke - Chris Sinclair
请参考https://dev59.com/sErSa4cB1Zd3GeqPYa1Z。这是一个特殊情况 - 如果您查看文档http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx,那么解释是“当更新发送到渲染线程时,渲染线程将更改的矩形从后台缓冲区复制到前台缓冲区。渲染系统控制此交换以避免死锁和重绘伪影,例如“撕裂”。 - dash
myImage.Dispatcher.Invoke - 相同的错误 - Nickon
1个回答

10
你的代码有两个问题:
  1. 如果你想要在不同于创建它的线程中访问WriteableBitmap,那么你需要先调用WriteableBitmap.Freeze()来冻结它。

  2. 在非派发器线程中无法访问myImage.Source

以下代码可以解决这两个问题:
private void doSomething()
{
    // ... bla bla bla
    colorBitmap = new WriteableBitmap(/* parameters */);
    colorBitmap.Freeze();
    Application.Current.Dispatcher.Invoke((Action)delegate
    {
        myImage.Source = colorBitmap;
    });
}

编辑 请注意,此方法允许您在线程中的任何位置创建和更新位图。一旦位图被冻结,它就不能再被修改了,这种情况下您应该丢弃它并创建一个新的。

顺便说一句,如果您不想阻塞线程更新myImage.Source,请使用BeginInvoke而不是Invoke


1
好的,它起作用了。现在没有错误了。但是当colorBitmap被冻结时如何编辑它?如何解冻它? - Nickon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接