C# WPF跨线程将位图数据流式传输到图像控件中
我有一个WPF应用程序,正在将摄像头帧从opencv DLL流式传输到UserControl中的C# WPF跨线程将位图数据流式传输到图像控件中,c#,wpf,multithreading,C#,Wpf,Multithreading,我有一个WPF应用程序,正在将摄像头帧从opencv DLL流式传输到UserControl中的Image控件中 这可以工作一段时间,然后崩溃,让我: 调用线程无法访问此对象,因为其他线程拥有它。 我的代码如下: 调用映像的类:(在线程中运行) //从位图到位图源的转换 public BitmapSource CameraFrame; [DllImport("gdi32")] private static extern int DeleteObject(IntPtr o); public s
Image
控件中
这可以工作一段时间,然后崩溃,让我:
调用线程无法访问此对象,因为其他线程拥有它。
我的代码如下:
调用映像的类:(在线程中运行)
//从位图到位图源的转换
public BitmapSource CameraFrame;
[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);
public static BitmapSource ToBitmapSource(Bitmap source)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
//显示图像的用户控件:
//xaml
<Image Name="ImageCameraFrame"/>
//线程函数:
private void InvokeMethodExample()
{
while (true)
{
ImageCameraFrame.Dispatcher.Invoke((Action)(() => ImageCameraFrame.Source = Dense.CameraFrame));
}
}
如上所述,这在一段时间内非常有效,然后崩溃。我的印象是,行CameraFrame.Freeze()
应该停止这种行为,但我显然做错了什么。这里需要互斥锁或类似的锁吗
谢谢。使用带有(可选异步)勾号处理程序的Dispatcher:
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(50)
};
timer.Tick += async (s, e) =>
{
ImageCameraFrame.Source = await Task.Run(() =>
{
var data = Dense.getFrame();
var format = PixelFormats.Rgb24;
var width = 640;
var height = 360;
var stride = (width * format.BitsPerPixel + 7) / 8;
var bitmap = BitmapSource.Create(width, height, 96, 96,
format, null, data, stride * height, stride);
bitmap.Freeze();
return bitmap;
});
};
timer.Start();
从代码中删除所有出现的
while(true)
。除此之外,为什么您要从原始像素缓冲区创建位图,以便立即将其转换为位图源,而您也可以直接从像素数据创建位图源?嗨,谢谢您的回答。如果我删除'while(true)`,图像将完全不显示……这是什么意思?如果要重复显示新帧,请使用计时器,例如Dispatcher。这些循环正在毫不延迟地杀死您的应用程序。被Dispatchermer替换,崩溃似乎已经消失。我假设这是因为计时器在UI线程上运行,我试图在没有安全性的情况下跨多个线程传递位图数据。非常感谢你!。。回到你最初的答复。。。我可以用同样的方法创建位图源吗?我是WPF的新手(显然)谢谢!这会在var Bitmap=…
上崩溃,并且“试图读取或写入受保护的内存”。这通常表明其他内存已损坏。缓冲区大小或跨距可能有问题。我无法测试它,因为我没有你的图像数据提供商。啊,明白了,我需要等待相机旋转起来,然后启动计时器。工作得很好。再次感谢您抽出时间。非常感谢。
private void InvokeMethodExample()
{
while (true)
{
ImageCameraFrame.Dispatcher.Invoke((Action)(() => ImageCameraFrame.Source = Dense.CameraFrame));
}
}
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(50)
};
timer.Tick += async (s, e) =>
{
ImageCameraFrame.Source = await Task.Run(() =>
{
var data = Dense.getFrame();
var format = PixelFormats.Rgb24;
var width = 640;
var height = 360;
var stride = (width * format.BitsPerPixel + 7) / 8;
var bitmap = BitmapSource.Create(width, height, 96, 96,
format, null, data, stride * height, stride);
bitmap.Freeze();
return bitmap;
});
};
timer.Start();