2011-08-12 9 views
2

イメージをBackgroundWorkerスレッドでディザリングしていて、イメージの処理が完了した後にUIを更新する必要があります。私が更新する必要がある画像は、DitherWorkerと同じクラスにあります。 BitmapSourceを渡して、記載されたエラーが発生しないようにするにはどうすればよいですか?BackgroundWorkerからオブジェクトを返す

public void DitherWorker() 
{ 
    double scalebox = Double.Parse(myWindow.scaleBox.Text); 
    int slider = (int)myWindow.convolutionBiasSlider.Value; 
    BitmapSource final = null; 
    ditherobj output = new ditherobj(scalebox, originalImage, slider);//.Get_Halftone(); 

    worker = new BackgroundWorker(); 
    worker.WorkerSupportsCancellation = true; 

    worker.DoWork += delegate(object s, System.ComponentModel.DoWorkEventArgs args) 
    { 
     ditherobj dob = (ditherobj)args.Argument; 
     Binarize bn = new Binarize(dob.scalebox, dob.localbms, dob.slider); 
     BitmapSource bms = (BitmapSource)bn.Get_Halftone(); 
     final = bms; 
     args.Result = new ditherobj(0,null,0,bms); 
    }; 

    worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
    { 
     ditherobj dob = (ditherobj)args.Result; 
     image1.Source = dob.localbms; //ERROR. The calling thread cannot access this object because another thread owns it 

     myWindow.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(() => 
     { 
      myWindow.activityBar.IsBusy = false; 
     })); 
    }; 

    worker.RunWorkerAsync((ditherobj)output); 
} 

public class ditherobj 
    { 
     public double scalebox; 
     public BitmapSource localbms; 
     public BitmapImage localbmi; 
     public int slider; 

     public ditherobj(double scalebox, BitmapImage localbmi, int slider, BitmapSource bms = null) 
     { 
      this.scalebox = scalebox; 
      this.slider = slider; 
      if (bms == null) 
      { 
       BitmapImage test = localbmi.Clone(); 
       localbms = (BitmapSource)test; 
      } 
      else 
       localbms = bms; 
     } 
    } 

問題を解決しました。 BitmapSourceは、渡される前にバックグラウンドスレッドで固定されている必要があります。ここでは、最終的なcomentedコードは次のとおりです。あなたがバックグラウンドスレッドで残っているとき

BackgroundWorker worker; 
    public void DitherWorker() 
    { 
     double scalebox = Double.Parse(myWindow.scaleBox.Text); //get values from UI for the job 
     int slider = (int)myWindow.convolutionBiasSlider.Value; 
     DitherSettings output = new DitherSettings(scalebox, originalImage, slider); //create holder object to be passed to BackgroundWorker 
     worker = new BackgroundWorker(); 

     worker.DoWork += delegate(object s, System.ComponentModel.DoWorkEventArgs args) 
     { 

      DitherSettings ds = (DitherSettings)args.Argument; //cast argument as our holder object 
      Binarize bn = new Binarize(ds.scalebox, ds.localbms, ds.slider); //create object to do our work 
      BitmapSource bms = (BitmapSource)bn.Get_Halftone(); //do work 
      bms.Freeze(); //freeze resulting BitmapSource so it can be utilized elsewhere 
      args.Result = new DitherSettings(0,null,0,bms); //create new object with resulting BitmapSource 

     }; 

     worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
     { 
      DitherSettings ds = (DitherSettings)args.Result; //get object with our BitmapSource 

      if (image1.Dispatcher.CheckAccess()) 
       this.image1.Source = ds.localbms; //update class image 

      myWindow.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(() => 
      { 
       myWindow.activityBar.IsBusy = false; //Update UI control 
      })); 
     }; 

     worker.RunWorkerAsync((DitherSettings)output); 

    } 

    public class DitherSettings 
    { 
     public double scalebox; 
     public BitmapSource localbms; 
     public BitmapImage localbmi; 
     public int slider; 

     public DitherSettings(double scalebox, BitmapImage localbmi, int slider, BitmapSource bms = null) 
     { 
      this.scalebox = scalebox; 
      this.slider = slider; 
      if (bms == null) 
       localbms = (BitmapSource)localbmi; 
      else 
       localbms = bms; 
     } 
    } 
+0

「ディテロビ」とは何ですか?スレッドの所有権と所有権の移転という概念は、.NETの中核ではありません。これがサードパーティのライブラリであれば、どのライブラリを使用していますか?それともあなたのクラスですか? – Jacob

+0

渡される値を保持する単純なオブジェクト。これを表示するために投稿を編集しました。 – PhilJ

+0

'ditherobj'クラス/構造体に' DitherSettings'という名前が付けられていないのはなぜですか? –

答えて

3

BitmapSourceFreeze()関数を呼び出します。

これは、オブジェクトを不変にするため、メインスレッドで使用できます。

Learn here more about freezable wpf objects.このページでは、Freezablesの他の多くの側面について説明していますが、「フリーズされたFreezableをスレッド間で共有することもできます。バックグラウンドスレッドでGUI要素(ビットマップなど)を構築するためにWPFで構築されたこの能力は、あなたが私に尋ねると、裏付けられていない#1 WPF機能です。

+0

ありがとう、フリーズ()はトリックをしました。 – PhilJ

0

BitmapSource.Clone()オブジェクトをコピーしたい場合は、何らかの用途があります。

Dispatcher.CheckAccess()は、image1.Sourceを設定する前に呼び出す必要があります。

+0

画像を設定する前にCheckAccess()を追加しました。 – PhilJ

関連する問題