【问题标题】:Error: Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher错误:即使使用 Dispatcher,也必须在与 DependencyObject 相同的线程上创建 DependencySource
【发布时间】:2014-10-14 12:38:46
【问题描述】:

以下是我的View 的一部分,其中我已将图像绑定到我的ViewModel 中的属性:

<Image Source="{Binding Image}"  Grid.Column="2" Grid.ColumnSpan="2"/>

我的ViewModel 是这个:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public BitmapImage Image
    {
        get { return _image; }
        set
        {
            _image = value;
            OnPropertyChanged();
        }
    }

    Action _makeScannerAlwaysOnAction;
    private BitmapImage _image;


    public MainWindowViewModel()
    {
        AddNewPersonCommand = new RelayCommand(OpenFrmAddNewPerson);
        FingerPrintScannerDevice.FingerPrintScanner.Init();
        MakeScannerAlwaysOn(null);
    }

    private void MakeScannerAlwaysOn(object obj)
    {
        _makeScannerAlwaysOnAction = MakeScannerOn;
        _makeScannerAlwaysOnAction.BeginInvoke(Callback, null);
    }

    private void Callback(IAsyncResult ar)
    {
        FingerPrintScannerDevice.FingerPrintScanner.UnInit();
        var objFingerPrintVerifier = new FingerPrintVerifier();
        objFingerPrintVerifier.StartVerifingProcess();
        var ms = new MemoryStream();
        ms.Position = 0;
        objFingerPrintVerifier.MatchPerson.Picture.Save(ms, ImageFormat.Png);
        var bi = new BitmapImage();
        bi.BeginInit();
        bi.StreamSource = ms;
        bi.EndInit();
        Thread.Sleep(2000);
        Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
        //Image = bi;

        _makeScannerAlwaysOnAction.BeginInvoke(Callback, null);
    }

    private void MakeScannerOn()
    {
        while (true)
        {
            if (FingerPrintScannerDevice.FingerPrintScanner.ScannerManager.Scanners[0].IsFingerOn)
            {
                return;
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

我的问题: 问题是当我想绑定图像时它给了我错误

必须在与 DependencyObject 相同的线程上创建 DependencySource

我用谷歌搜索了很多,我在 SO 中看到了帖子,但它们都不适合我。

任何形式的帮助将不胜感激。

【问题讨论】:

  • 在创建之后尝试bi.Freeze(),在更新之前尝试Image
  • 哦,谢谢。它就像魔术一样起作用。它有什么作用?我认为这可能是一个线程问题。尝试发布答案以被接受
  • msdn.microsoft.com/en-us/library/ms750509(v=vs.110).aspx 应该为您提供所需的有关冻结的信息。
  • 我们看不到的是谁在创建图像以及属性是如何设置的。这是我的想法,你应该分拆这样的任务。 Task.Run((//在这里做图像的东西)=>);当任务完成时,它会自动加入 GUI 线程,如果它是从那里分离出来的。此外,它也会快 5 倍左右。

标签: c# .net wpf multithreading xaml


【解决方案1】:

BitmapImageDependencyObject,所以它在哪个线程上创建确实很重要,因为您无法访问在另一个线程上创建的对象的DependencyProperty,除非它是一个Freezable 对象并且您可以Freeze 它。

使当前对象不可修改并将其 IsFrozen 属性设置为 true。

您需要做的是在更新Image之前致电Freeze

bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();

Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);

正如@AwkwardCoder 指出的,这里是Freezable Objects Overview

【讨论】:

  • 对于从 ImageSource 创建驱动程序的视频流非常有用,特别是因为在 UI 的同步上下文上运行采集非常昂贵并且会导致 UI 冻结。 +1 队友!
  • 如果我不想更新Image,其中Freeze 方法可用但例如ObservableCollection&lt;T&gt; 类型的属性,该怎么办? Freeze 方法在该类型中不可用...
猜你喜欢
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-28
  • 2020-07-24
  • 2020-06-29
相关资源
最近更新 更多