即使使用 Dispatcher WPF,也必须在与 DependencyObject 相同的线程上创建 DependencySource

Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher WPF

我正在编写一个 C# WPF 应用程序,我正在使用 AForge 库进行视频流。 我想部署应用程序,因为第一台电脑上一切正常。

比我部署它和在另一台电脑上我得到以下错误:

"Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher"

这是源代码,我在从网络摄像头获得的每个新帧上调用它

private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)

{ 如果(StreamRunning) { 尝试 { 使用 (var bitmap = (Bitmap)eventArgs.Frame.Clone()) {

                    Image = ToBitmapImage(bitmap);
                }
                Image.Freeze();
            }
            catch (Exception e)
            {
                UIMessages = "Error: NewFrame " + e.Message;
            }
        }

}

ToBitmapImage 方法:

        private BitmapImage ToBitmapImage(Bitmap bitmap)
    {

        var start = 420;
        var end = 1920 - 2* 420;
        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        MemoryStream ms = new MemoryStream();
        Bitmap source = bitmap;
        Bitmap CroppedImage = source.Clone(new System.Drawing.Rectangle(start, 0, end, 1080), source.PixelFormat);          
        CroppedImage.Save(ms, ImageFormat.Bmp);

        ms.Seek(0, SeekOrigin.Begin);
        bi.StreamSource = ms;
        bi.EndInit();
        return bi;
    }

更多代码:

 private BitmapImage _image;
 public BitmapImage Image {
        get => _image;
        set
        {
            _image = value;
            OnPropertyChanged();
        }
    }

相机的启动:

            if (SelectedDevice != null)
            {
                _videoSource = new VideoCaptureDevice(SelectedDevice.MonikerString);
                //var test = _videoSource.VideoCapabilities;
                _videoSource.NewFrame += video_NewFrame;
                _videoSource.Start();


            }

UI:

 <Image Height="400" Width="400" Source="{Binding Image, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,0"/>

我也试过这个:

 Dispatcher.CurrentDispatcher.Invoke(() => Image = ToBitmapImage(bitmap));

从 Stream 加载 BitmapImage 时,通常会通过设置 BitmapCacheOption.OnLoad.

尽快关闭 Stream 并确保立即加载 BitmapImage
private static BitmapImage ToBitmapImage(Bitmap bitmap)
{
    var start = 420;
    var end = 1920 - 2 * 420;

    var croppedBitmap = bitmap.Clone(
        new System.Drawing.Rectangle(start, 0, end, 1080),
        bitmap.PixelFormat);          

    var bi = new BitmapImage();

    using (var ms = new MemoryStream())
    {
        croppedBitmap.Save(ms, ImageFormat.Bmp);
        ms.Seek(0, SeekOrigin.Begin);

        bi.BeginInit();
        bi.CacheOption = BitmapCacheOption.OnLoad;
        bi.StreamSource = ms;
        bi.EndInit();
    }

    bi.Freeze();

    return bi;
}