2013-10-11 4 views
0

내 응용 프로그램의 주 스레드에서 처리되고 렌더링되고 표시되는 WPF 컨트롤이 있습니다. 이 컨트롤은 수천 개의 데이터 포인트를 "레이어"라는 개체의 뷰로 업로드합니다. 이 "레이어"객체의 생성 과정부터다중 스레드 환경 문제

public class WPFControl{ 

    private List<Layer> myLayers; 

    public List<Layer> MyLayers{ 
     get{ return myLayer;} 
    }  

    ... 
} 

public class Layer{ 
    private List<DataPoint> myDataPoints; 

    public List<DataPoint> MyDataPoints{ 
     get{ return myDataPoints;} 
    } 

    ... 
} 

public class DataPoint{ 
    .... 
} 

때문에 읽고 업로드 할 수있다 DataPoint에 수천의 시간은 내가, 걸립니다 다음은 객체/클래스 계층 구조처럼 보이는 방법에 대한 대략적인 설명입니다 그 레이어 객체를 다른 스레드에 생성합니다. 그건 잘 작동하고 레이어 개체를 매우 잘 반환합니다.

myWpfControl.MyLayers.Add(layerCreatedInOtherThread); 

WPF 컨트롤 불이 오류 :

The calling thread cannot access this object because a different thread owns it 

내가 좋아, 그럼 내가 사용할 수있는 생각을 나는 다음과 같이 표시 할 행하고자 시도 WPF 컨트롤에 추가 할 때 문제는 다음과 같은 운영자 :

myWpfControl.Dispatcher.Invoke((Action) 
(()=>{         
    myWpfControl.MyLayers.Add(layerCreatedInOtherThread); 
}) 
); 

하지만 계속 동일한 오류가 발생합니다. 이 문제를 어떻게 해결할 수 있을지 생각해?

+2

이 작업을 수행 할 수 없습니다. UI는 데이터가 아닙니다. 백그라운드 스레드에서 데이터를 가져오고 데이터는 절차 코드로 조작하는 대신 UI를 바인딩합니다. –

+1

'다른 스레드에서 해당 레이어 객체를 생성합니다. '코드를 표시하십시오. –

+0

우선 순위 바인딩 및 백그라운드 작업자를 찾습니다 – Paparazzi

답변

0

BackgroundWorker을 사용하면 다른 스레드에서 작업을 실행할 수 있으며 완료되면 UI 스레드의 결과에 액세스 할 수 있습니다.

private System.ComponentModel.BackgroundWorker bgWorker; 
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); 
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); 

//Start the work 
bgWorker.RunWorkerAsync(null) //you can send an argument instead of null 

private void backgroundWorker1_DoWork(object sender, 
     DoWorkEventArgs e) 
    { 
     // Get the BackgroundWorker that raised this event. 
     BackgroundWorker worker = sender as BackgroundWorker; 

     // Assign the result of the computation 
     // to the Result property of the DoWorkEventArgs 
     // object. This is will be available to the 
     // RunWorkerCompleted eventhandler. 
     e.Result = CreateLayerInOtherThread(); //if you sent an arg instead of null it as availalbe in e.Argument and can be cast from object. 
    } 

이 결과가 한 번 완료하기 업무를 수행합니다. 이것은 UI 스레드에서 실행되므로 업데이트 할 수 있습니다.

private void bgWorker_RunWorkerCompleted(
     object sender, RunWorkerCompletedEventArgs e) 
    { 
     // First, handle the case where an exception was thrown. 
     if (e.Error != null) 
     { 
      MessageBox.Show(e.Error.Message); 
     } 
     else if (e.Cancelled) 
     { 
      // Next, handle the case where the user canceled 
      // the operation. 
      // Note that due to a race condition in 
      // the DoWork event handler, the Cancelled 
      // flag may not have been set, even though 
      // CancelAsync was called. 


     } 
     else 
     { 
      // Finally, handle the case where the operation 
      // succeeded. 
      Layer myLayer = (Layer)e.Result; 
      myWpfControl.MyLayers.Add(myLayer); 
     } 


    } 
+0

배경 스레드가'DispatcherObject'에서 파생 된 객체를 생성하기 때문에 이것은 작동하지 않을 것이다. 과정은 "기본"발송자와 관련이 없습니다. –

+0

@ HighCore. 왜 이것이 작동하지 않을지 모르겠다. 나는 당신의 의견을 이해하지 못한다. BackgorundWorker의 목적은 다른 스레드에서 작업을 실행 한 다음 완료되면 Dispatcher에 액세스하는 것입니다. 이 대답을 삭제 하시겠습니까? 당신은 해결책으로 무엇을 제안합니까? – Harrison

+0

자신을 명확히하기 위해, OP는 백그라운드 스레드에서 UI 요소를 만들고있을 것입니다. 작동 할 방법이 없습니다. 그는 UI와 데이터를 모두 망가 뜨리므로 단일 스레드 시나리오가 필요합니다. 백그라운드 스레드에서 UI 요소를 작성하여 다른 스레드의 Dispatcher에서 작동시킬 수있는 방법은 없습니다. Winforms와 같은 접근 방식과는 달리 항상 제안 된 솔루션은 MVVM과 DataBinding입니다. –

관련 문제