程序在WCF接受双工回调: public void UpdateVideo(byte[] bytesVideo)
{
try
{
if (bytesVideo != null)
{
this.mainWindowViewModel.VideoInSource = Service.VideoManager.ConvertByteArrayToImageSource(bytesVideo);
}
}
catch (Exception ex)
{
Logger.Instance.Error(ex.Message, ex);
}
}上面是将回调的二进制转换为ImageSource对像赋值给我的mainWindowViewModel
然后mainWindowViewModel有定义 private System.Windows.Media.ImageSource videoInSource;
/// <summary>
/// 远程视频数据
/// </summary>
public System.Windows.Media.ImageSource VideoInSource
{
get
{
return videoInSource;
}
set
{
this.videoInSource = value;
//this.RaisePropertyChanged("VideoInSource");
}
}现在是屏蔽掉了this.RaisePropertyChanged("VideoInSource");的话程序正常
如果我不屏蔽的话,在VideoInSource通知XAML重新绑定时报错:
必须在与 DependencyObject 相同的线程上创建 DependencySource我在Baidu上看意思是说ImageSource不能多线程之类的,但是没有解决方法
上Google这几天都上不了,不知道是什么原因大家帮看一下如何处理谢谢
{
try
{
if (bytesVideo != null)
{
this.mainWindowViewModel.VideoInSource = Service.VideoManager.ConvertByteArrayToImageSource(bytesVideo);
}
}
catch (Exception ex)
{
Logger.Instance.Error(ex.Message, ex);
}
}上面是将回调的二进制转换为ImageSource对像赋值给我的mainWindowViewModel
然后mainWindowViewModel有定义 private System.Windows.Media.ImageSource videoInSource;
/// <summary>
/// 远程视频数据
/// </summary>
public System.Windows.Media.ImageSource VideoInSource
{
get
{
return videoInSource;
}
set
{
this.videoInSource = value;
//this.RaisePropertyChanged("VideoInSource");
}
}现在是屏蔽掉了this.RaisePropertyChanged("VideoInSource");的话程序正常
如果我不屏蔽的话,在VideoInSource通知XAML重新绑定时报错:
必须在与 DependencyObject 相同的线程上创建 DependencySource我在Baidu上看意思是说ImageSource不能多线程之类的,但是没有解决方法
上Google这几天都上不了,不知道是什么原因大家帮看一下如何处理谢谢
http://social.msdn.microsoft.com/Forums/hu-HU/wpf/thread/9b96e34d-f7d4-41bb-b793-0cdc08fb3618
http://stackoverflow.com/questions/4690781/must-create-dependencysource-on-same-thread-as-the-dependencyobject
{
this.mainWindowViewModel.window.Dispatcher.BeginInvoke(new System.Threading.ThreadStart(() =>
{
this.mainWindowViewModel.VideoInSource = Service.VideoManager.ConvertByteArrayToImageSource(bytesVideo);
}));
}解决了
但是这样不符合MVVM,因为我把window传给了这个MVVM最好的办法是怎么样?谢谢
楼上的方法都是不需要传window作为参数的。
2楼的链接里方法是: /// <summary>
/// 远程视频数据
/// </summary>
public System.Windows.Media.ImageSource VideoInSource
{
get { return videoInSource; }
set
{
this.videoInSource = value;
this.videoInSource.Freeze(); // 冻结后就可以跨线程用作绑定源
this.RaisePropertyChanged("VideoInSource");
}
}3楼的方法我臆测一下可能是这样: // 用byte数组来保存接收到视频数据
private byte[] _videoInSourceData;
public byte[] VideoInSourceData
{
get { return _videoInSourceData; }
set
{
_videoInSourceData = value;
videoInSource = null; // 需要让VideoSource重新生成
this.RaisePropertyChanged("VideoInSource");
}
} private System.Windows.Media.ImageSource videoInSource; /// <summary>
/// 远程视频数据
/// </summary>
public System.Windows.Media.ImageSource VideoInSource
{
get
{
// 延迟到UI来请求数据时再创建对象,这时是在主线程上创建
return videoInSource ?? Service.VideoManager.ConvertByteArrayToImageSource(VideoInSourceData);
}
}
然后在回调方法中改成记录接收到的数据,而不用创建ImageSource实例: public void UpdateVideo(byte[] bytesVideo)
{
try
{
if (bytesVideo != null)
{
this.mainWindowViewModel.VideoInSourceData = bytesVideo;
}
}
catch (Exception ex)
{
Logger.Instance.Error(ex.Message, ex);
}
}
我这里没有用Converter,但大概意思和3楼应该是一样的。你自己的方法也是可以的,这种写法的原理是把创建ImageSource的代码列集到主线程去执行,
而获取主线的方法并不需要传窗口,可以这样:
Application.Current.Dispatcher.BeginInvoke(new Action(() => { }));
谢谢