继上篇博客结束后,一秒钟30张图片,image控件刷图片的方法经常被抢了焦点,继而出现经常白屏,而且主线程也经常卡死。
后来查了下资料,BitImage对象在给image.Source的时候调用一下Freeze方法,可以实现bitmap对象的跨线程访问,出现白屏的次数少了,但白屏还会有。
经过经验测试,用WPF的Image显示视频数据,数据量过大肯定会有白屏。
所以后来又换成了之前的Picturbox控件,在WPF控件中加入了PictureBox控件。
以下代码只是实现了BItmapImage对象的多线程访问。
while (true) { try { nRev = _WinSkt.Receive(nMsgLenBuf); } catch { return; } try { _lenstart = (nMsgLenBuf[0] * 256 + nMsgLenBuf[1]) * 2; YuvClass.yv12_rgb_convert(nMsgLenBuf, 2, RgbBuf, Convert.ToInt32(_width), j);//转换的有效RGB图片数据 buffstream.Position = j * _lenstart + 54; //丢失的数据包直接不管,找到当前包其所在的位置并写入 buffstream.Write(RgbBuf, 0, j * 2); if (_lenstart + 2 >= _height - 1) //一张图片传结束了 { imgstream.Position = 0; //解决buff被接收线程修改的问题,将buff中的数据复制到图片内存区 imgstream.Write(buffstream.GetBuffer(), 0, _length + 54); BitmapImage bmpp = new BitmapImage(); bmpp.BeginInit(); bmpp.StreamSource = imgstream; bmpp.EndInit(); bmpp.Freeze(); Application.Current.Dispatcher.BeginInvoke(_dShowpic2, bmpp); //显示图片 } } catch { buffstream.Dispose();//重新实例化内存缓存 buffstream = new MemoryStream(); buffstream.Write(_header, 0, 54); imgstream.Dispose(); imgstream = new MemoryStream(); } }
之前bitmapImage是在_dshowpic所在委托中实例化的,现在移到了子线程中,所以主线程的压力变小了,通过Freeze()方法,可以将子线程中实例化的图片安全送给主线程显示。
白屏的情况还会有,继续研究中。