【问题标题】:Threading with WPF Images (System.InvalidOperationException)使用 WPF 图像进行线程处理 (System.InvalidOperationException)
【发布时间】:2011-05-04 01:12:10
【问题描述】:

我正在使用线程从网站获取图像并将其拍摄回父表单 (WPF) 以显示。我遇到了一个问题,并设法将它调试到这个例子:

public void Watch()
{
  while (true)
  {
    Bitmap bmp = new Bitmap(1, 1);
    BitmapImage bmpImg = new BitmapImage();

    this.SetImage(bmp, bmpImg);
  }
}

public delegate void SetImageCallback(Bitmap bmp, BitmapImage bmpImg);

private void SetImage(Bitmap bmp, BitmapImage bmpImg)
{
  if (!this.imgVideo.Dispatcher.CheckAccess())
  {
    SetImageCallback del = new SetImageCallback(SetImage);
    this.Dispatcher.Invoke(del, bmp, bmpImg);
  }
  else
  {
    Bitmap bitmap = bmp;
    BitmapImage bitmapImage = bmpImg;
  }
}

请记住 Watch() 在它自己的线程上运行。如果我使用位图对象(我可以在窗口窗体中与 PictureBox 一起使用),一切都会很好。也就是调试这段代码,当我到了那一行

Bitmap bitmap = bmp;

并检查变量 bmp,一切都很好并且按预期工作。但是,当我到达下一行时

BitmapImage bitmapImage = bmpImg;

并检查变量 bmpImage,我得到大量 System.InvalidOperationException。当这在实践中并被分配给 WPF Image 对象时,它会说“调用线程无法访问此对象,因为不同的线程拥有它。”为什么我在 WPF BitmapImages(设置 ImageSource 所必需的)中遇到此问题,但在 Windows 窗体 Bitmap 对象(可用于设置 PictureBox)中却没有?如何在 WPF 中解决此问题?

【问题讨论】:

标签: wpf multithreading imagesource


【解决方案1】:

WPF 中的大多数对象都属于这一类:它们不能在不同线程之间共享。但是,某些低级资源(例如画笔和位图)派生自一个名为 Freezable 的特殊类,如果冻结,可以在不同线程之间共享。当然,一旦对象被冻结,就不能再以任何方式进行修改。要冻结可冻结对象,只需调用Freeze,这将防止跨线程异常。

【讨论】:

  • 好的,所以我开始尝试使用 BitmapImage 和 ImageBrush(源分配给 BitmapImage),但我不断收到“无法冻结此 Freezable”错误。为什么我会得到这个?
  • 这与我从 URL 获取图像的来源有关吗?看起来我遇到了this 问题,但无法引发 DownloadCompleted 事件。另外,如果我检查 IsDownlading 属性,它总是正确的。我该怎么办?
【解决方案2】:

代替

if (!this.imgVideo.Dispatcher.CheckAccess())
  {
    SetImageCallback del = new SetImageCallback(SetImage);
    this.Dispatcher.Invoke(del, bmp, bmpImg);
  }

尝试使用:

if (!App.Current.Dispatcher.CheckAccess())
                App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action<CustomObject>(SetImage),CustomeObjectInstance );

这里的Cutom对象将是一个包装类包装

Bitmap bmp, BitmapImage bmpImg

显然,您的 SetImage 签名将更改为

SetImage(CutomObject custObj)

我没有测试过代码,但这可能会解决问题。 让我们知道这是否有效,以便一些可怜的灵魂可以从这篇文章中受益。 一切顺利! 席德

【讨论】:

    猜你喜欢
    • 2018-12-17
    • 1970-01-01
    • 2013-10-11
    • 2020-02-04
    • 1970-01-01
    • 2011-06-13
    • 2012-11-17
    • 1970-01-01
    相关资源
    最近更新 更多