程序在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这几天都上不了,不知道是什么原因大家帮看一下如何处理谢谢

解决方案 »

  1.   

    http://stackoverflow.com/questions/7865514/must-create-dependencysource-on-same-thread-as-dependencyobject
    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
      

  2.   

    建议回调里先保存图片,修改 ImagePath 并通知 ImagePath 变更。Xmal 里做一个 Path to ImageSource 的Converter 
      

  3.   

    我用                if (bytesVideo != null)
                    {
                        this.mainWindowViewModel.window.Dispatcher.BeginInvoke(new System.Threading.ThreadStart(() =>
                           {
                               this.mainWindowViewModel.VideoInSource = Service.VideoManager.ConvertByteArrayToImageSource(bytesVideo);
                           }));
                    }解决了
    但是这样不符合MVVM,因为我把window传给了这个MVVM最好的办法是怎么样?谢谢
      

  4.   

    来晚了,呵呵。
    楼上的方法都是不需要传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(() => {  }));
      

  5.   

    “这个MVVM”? MVVM就是以表现层控件为核心的,不是只有数据。你的mainWindowViewModel既然包含Window属性,它就是表现层。否则,它不应该暴露Window属性,而应该自己去处理Window访问问题(也就是说在其暴露的代码内部去执行Dispatch.BeginInvoke。
      

  6.   

    我原来就是没有引用Window的,但后来为了解决这个问题才引进来的
    谢谢