2011-08-12 3 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는 전달되기 전에 백그라운드 스레드에서 동결되어야합니다. 당신이 백그라운드 스레드에서 아직 때

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() 기능 : 여기에 최종 comented 코드입니다.

개체를 변경할 수 없으므로 주 스레드에서 사용할 수 있습니다.

Learn here more about freezable wpf objects.이 페이지에서는 Freezables의 다른 여러 측면에 대해 설명하지만 "Freeze Freeze는 스레드간에 공유 될 수도 있습니다 ..."라고 명시 적으로 설명합니다. 배경 스레드에서 GUI 요소 (예 : 비트 맵)를 작성하기 위해 WPF에 내장 된이 기능은 저에게 묻는다면 # 1 우연한 WPF 기능입니다.

+0

고맙습니다. Freeze()가 트릭을했습니다. – PhilJ

0

BitmapSource.Clone() 개체를 복사하려는 경우 사용할 수 있습니다.

Dispatcher.CheckAccess()은 image1.Source를 설정하기 전에 호출해야합니다.

+0

이미지를 설정하기 전에 CheckAccess()를 추가하십시오. – PhilJ

관련 문제