WPF图像的持续(快速)更新

时间:2011-05-03 00:56:22

标签: wpf multithreading image

有一个网站包含来自网络摄像头的单个图像。每次点击网站时,都会显示网络摄像头的最新图像。我想通过持续点击网站来制作实时视频。

我已经搜索并尝试了几件事,但无法以合理的速度刷新它。

public MainWindow()
{
  InitializeComponent();

  this.picUri = "http://someurl";
  this.thWatchVideo = new Thread(new ThreadStart(Watch));

  _image = new BitmapImage();
  _image.BeginInit();
  _image.CacheOption = BitmapCacheOption.None;
  _image.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
  _image.CacheOption = BitmapCacheOption.OnLoad;
  _image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
  _image.UriSource = new Uri(this.picUri);
  _image.EndInit();
  this.imgVideo.Source = _image;

  this.thWatchVideo.Start();
}

public void Watch()
{
   while(true)
   {
     UpdateImage();
   }
}

 public void UpdateImage()
{
  if (this.imgVideo.Dispatcher.CheckAccess())
  {
     _image = new BitmapImage();
     _image.BeginInit();
     _image.CacheOption = BitmapCacheOption.None;
     _image.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
     _image.CacheOption = BitmapCacheOption.OnLoad;
     _image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
     _image.UriSource = new Uri(this.picUri);
     _image.EndInit();
     this.imgVideo.Source = _image;
  }
  else
  {
    UpdateImageCallback del = new UpdateImageCallback(UpdateImage);
    this.imgVideo.Dispatcher.Invoke(del);
  }
}

问题是,这太慢了,刷新时间太长,应用程序就会挂起。

我使用PictureBox控件在Windows窗体中使用它,但无法在WPF中使用它。我拒绝相信WPF不如形式。

4 个答案:

答案 0 :(得分:1)

此应用程序将始终挂起(无论是winforms还是WPF),因为您有一个无限循环运行它在UI线程上执行的所有操作。您的应用程序挂起,因为您不允许UI线程随时处理用户输入(例如调整窗口大小或尝试关闭应用程序)。

关于您的表现:您是否尝试过分析代码?我怀疑这个问题与您反复敲击网络服务器的图像有关,因为您永远不可能获得足够的每秒请求来从静态图像制作任何类型的实时视频。 (我们有视频流编解码器的原因!)

答案 1 :(得分:0)

而不是重新创建整个图像尝试仅更改UriSource属性。

答案 2 :(得分:0)

我建议Bitmap图像是在非GUI线程上创建的依赖项对象。然后在GUI线程上调用UpdateImage。由于位图图像依赖关系对象未在GUI线程的/(由其拥有)上创建,因此您将获得“其他线程拥有它”错误。

作为一种解决方法怎么样?

  1. 将图像临时复制到Watch例程中的本地文件位置。
  2. 在监视例程中添加Thread.Sleep,这样就不会在此线程上使用无限循环敲击CPU。
  3. 使用BeginInvoke代替Invoke
  4. 在UpdateImage例程中加载并更新图像,以便图像和imgVideo对象位于GUI线程上。通过从本地文件副本中读取映像来更新映像。
  5. 不知道如何让Watch在自己的线程上运行(使用Background worker?)我认为这种方法对你有用。

答案 3 :(得分:0)

查看我对此的回答:Showing processed images from an IP camera

另外,请确保在单独的线程上完成通信。