即使使用 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;
}
我正在编写一个 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
.
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;
}