2010-08-03 3 views
2

솔직히 솔직히 말하면 조금 실망 스럽습니다;) 그래서 약간의 도움을 요청합니다.서브 스레드와 메인 스레드 동기화하기 - 명백한 문제가 아닙니다.

일부 차트를 그릴 수있는 몇 가지 종류의 컨트롤이 있다고 가정 해 봅시다. 이 컨트롤에 차트를 그리는 방법도 있습니다. 문제는 차트 메서드가 컨트롤 필드 중 하나에만 액세스 할 수 있으므로 차트가 준비되면 컨트롤을 새로 고쳐야한다는 것입니다.

그럼 우리의 통제가 보이는 가정 해 봅시다 : Canvas 이미지 (그래픽 같은)을 그리는 데 사용하는 클래스입니다

class ChartingControl : System.Windows.Forms.Control 
{ 
    public Canvas canvas; 
    public void Refresh(); 
    /* 
    ... other fields/methods 
    */ 
} 

.
차트 작성 방법 만 canvas 객체 (우리는 변경할 수 없습니다)에 액세스 할 수있는, 그래서 그 모양 :이 방법은 등 별도의 스레드, 배경 노동자에서 호출 할 수

public static void DrawChart(canvas) 
{ /* draw */ } 

... 그리고 차트가 준비되면 기본 스레드와 동기화하고 Refresh()으로 호출해야합니다. 차트가 준비되면

는 지금, 나는 캔버스 객체

public static void DrawChart(canvas) 
{ /* draw */ 
    canvas.Tag = true; // chart is ready 
} 

에 플래그를 설정 그리고 나는 배경 작업자가 차트 컨트롤의 내부 실행하고 canvas.Tag 필드가 변경된 경우, 듣기, 그렇다면이 그것은 Refresh()

그러나 내 방법은 약간 거친 것 같고, 쉽게 실패하는 등 ... 어떤 개선 된 방법이 있습니까?

제한 사항 :
- Canvas 클래스는 수정할 수 없습니다. 우리가 사용할 수있는 유일한 방법은 (유형 object
Tag 필드 - 우리가 ChartingControl 클래스와 그리기 방법을 수정할 수 있습니다
-. 많은 차트 컨트롤의
가있을 수 있습니다 -. 우리는 DrawChart가 호출 방식을 제어 할 수 없다는 그것은 수 별도의 스레드에서 호출, 또는하지 수. 그것은 다른 곳이라고합니다. 우리가 할 수있는 모든 컨트롤과 DrawChart 방법을 만들고 어떻게 든 그들을 comunicate 수하는 것입니다

해결책
OK, 나는 이런 식으로 해결 : ChartingControl에서 나는 ManualResetEvent manualReset과 배경 작업자를 만들었습니다.

void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 
      manualReset.WaitOne(); // Wait for a chart to be ready 
    } 

및 차트 때 결국

void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
    { 
     Refresh(); 
    } 

내가 canvas.Tag 내부 및 도면에있어서 내부 manualReset 객체를 전달 리셋() 메소드를 호출

배경이 작업자 manualReset 기다린다 준비 완료 manualReset.Set();으로 전화하여 차트 준비 신호를 전달하십시오.

+0

DrawChart 메서드가 새 스레드를 시작하거나 다른 스레드에서 호출합니까? –

+0

다른 스레드에서 호출합니다 – Gacek

답변

1

도움이 될 것입니다 차트를 그립니다 다른 스레드에서
myChartingControl.Invoke(new Action(myChartingControl.Refresh));
을 할 것을 권장합니다 좋습니다, 저는이 방법으로 해결했습니다 : ChartingControl에서 나는 ManualResetEvent manualReset과 배경 작업자를 만들었습니다.

void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 
      manualReset.WaitOne(); // Wait for a chart to be ready 
    } 

및 차트 때 결국

void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
    { 
     Refresh(); 
    } 

내가 canvas.Tag 내부 및 도면에있어서 내부 manualReset 객체를 전달 리셋() 메소드를 호출

배경이 작업자 manualReset 기다린다 준비 완료 manualReset.Set();으로 전화하여 차트 준비 신호를 전달하십시오.

+0

당신은 올바른 선택을했습니다. IMO - 자신의 게시물에 답변을 게시하는 대신 OP를 업데이트 할 수 있습니까? 한 곳에서 문제와 솔루션을 더 쉽게 볼 수 있습니다. – zebrabox

0

캔버스 개체에 대한 액세스의 동기화를 처리 가정하면, 난 그냥

+0

차트를 그리는 스레드에서 차트 컨트롤에 액세스 할 수 없습니다 :/ – Gacek

+0

하지만 어떻게 든 캔버스에 대한 참조를 전달합니까? 즉, 컨트롤에 대한 참조를 전달하고 거기에서 캔버스를 가져올 수 있습니다. – ULysses

+0

다른 곳에서 사용되는 라이브러리를 만듭니다. 이 컨트롤에는 Canvas 객체가 포함되어 있으며 사용되는 응용 프로그램에서 새 컨트롤이 만들어진 후 'DrawChart (chartingControl.canvas)'가 호출됩니다 (직접 또는 하위 스레드) – Gacek

0

BackgroundWorker 당신에게

void StartDrawChart(){ 

     BackgroundWorker bw = new BackgroundWorker(); 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
     bw.RunWorkerAsync() 
    } 


    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     this.Refresh(); 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     DrawChart(this.canvas); 
    } 
+0

예,'DrawChart' 메서드가 호출되는 방법을 제어 할 수 있다면 솔루션이 될 것입니다. 그러나 그것은 다른 곳에 사용되며 나는 그것을 제어 할 수 없습니다. 나는 내 질문을 업데이트 할 것이다. – Gacek

관련 문제