web-dev-qa-db-ja.com

エラー:Dispatcherを使用しても、DependencyObjectと同じスレッドにDependencySourceを作成する必要があります

以下は、Viewの一部であり、ViewModelのプロパティにImageをバインドしています。

<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で投稿を見ましたが、どちらも機能しませんでした。

どんな種類の助けも大歓迎です。

24

BitmapImageDependencyObjectであるため、別のスレッドで作成されたオブジェクトのDependencyPropertyにアクセスできないのは、それが Freezable オブジェクトであり、かつ Freeze it 。

現在のオブジェクトを変更不可にし、そのIsFrozenプロパティをtrueに設定します。

Freezeを更新する前にImageを呼び出す必要があります。

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

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

@AwkwardCoderが指摘しているように、ここは Freezable Objects Overview です

69
dkozl