2

スレッドを使用してWebサイトから画像を取得し、それを親フォーム(WPF)に戻して表示しています。問題が発生し、次の例にデバッグすることができました。

public void Watch()
{
  while (true)
  {
    Bitmap bmp = new Bitmap(1, 1);
    BitmapImage bmpImg = new BitmapImage();

    this.SetImage(bmp, bmpImg);
  }
}

public delegate void SetImageCallback(Bitmap bmp, BitmapImage bmpImg);

private void SetImage(Bitmap bmp, BitmapImage bmpImg)
{
  if (!this.imgVideo.Dispatcher.CheckAccess())
  {
    SetImageCallback del = new SetImageCallback(SetImage);
    this.Dispatcher.Invoke(del, bmp, bmpImg);
  }
  else
  {
    Bitmap bitmap = bmp;
    BitmapImage bitmapImage = bmpImg;
  }
}

Watch()は独自のスレッドで実行されることに注意してください。ビットマップオブジェクト(ウィンドウフォームのPictureBoxで使用できます)を使用すると、すべてがうまく機能します。つまり、私が行に着いたときに、このコードをデバッグします

Bitmap bitmap = bmp;

そして、変数bmpを調べてください。すべてが素晴らしく、期待どおりに機能します。しかし、次の行にたどり着くと

BitmapImage bitmapImage = bmpImg;

そして、変数bmpImageを調べて、大量のSystem.InvalidOperationExceptionを取得します。これが実際に行われ、WPF Imageオブジェクトに割り当てられると、「別のスレッドがオブジェクトを所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません」と表示されます。WPF BitmapImages(ImageSourceの設定に必要)でこの問題が発生するのに、WindowsフォームのBitmapオブジェクト(PictureBoxの設定に使用できる)では発生しないのはなぜですか?これをWPFで修正するにはどうすればよいですか?

4

2 に答える 2

4

WPFのほとんどのオブジェクトはこのカテゴリに属し、異なるスレッド間で共有することはできません。ただし、ブラシやビットマップなどの特定の低レベルリソースはFreezable、フリーズすると異なるスレッド間で共有できるという特別なクラスから派生します。もちろん、オブジェクトがフリーズすると、それ以上変更することはできなくなります。フリーズ可能なオブジェクトをフリーズするには、を呼び出すだけでFreeze、クロススレッド例外を防ぐことができます。

于 2011-05-04T02:25:30.067 に答える
1

それ以外の

if (!this.imgVideo.Dispatcher.CheckAccess())
  {
    SetImageCallback del = new SetImageCallback(SetImage);
    this.Dispatcher.Invoke(del, bmp, bmpImg);
  }

使用してみてください:

if (!App.Current.Dispatcher.CheckAccess())
                App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action<CustomObject>(SetImage),CustomeObjectInstance );

ここで、Cutomオブジェクトはラッパークラスラッピングになります

Bitmap bmp, BitmapImage bmpImg

明らかに、SetImage署名は次のように変更されます

SetImage(CutomObject custObj)

コードをテストしていませんが、これで問題が解決する可能性があります。この投稿から一部の貧しい魂が恩恵を受けることができるようにこれが機能するかどうかをお知らせください。ではごきげんよう!シド

于 2011-05-04T11:31:48.777 に答える