Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF跨线程将位图数据流式传输到图像控件中_C#_Wpf_Multithreading - Fatal编程技术网

C# WPF跨线程将位图数据流式传输到图像控件中

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

我有一个WPF应用程序,正在将摄像头帧从opencv DLL流式传输到UserControl中的
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();