继上篇博客结束后,一秒钟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()方法,可以将子线程中实例化的图片安全送给主线程显示。
白屏的情况还会有,继续研究中。