2012-03-01 2 views
-2

두 스레드가 동시에 클래스의 메서드를 실행하는 응용 프로그램에서 작업하고 있습니다. 이 메서드는 몇 가지 복잡한 계산을 수행하고 결과는 WinForm에 표시됩니다. (나는 스레드 안전 방법을 사용하는 것처럼) 각 스레드가의 WinForm에서 Label 다른 그래서, 내가 스레드 동기화에 대한 어떤 문제를 예상하지 업데이트C#은 스레드 전환을 어떻게 처리합니까?

class Comp_func 
{ 
    /* Constructor */ 
    public Comp_func() 
    { 
    } 

    public void THE_Complex_func(string One, Int16 Two, Int32 Three) 
    { 
     Calculate_this(One); 
     Thread.Sleep(10); 
     Calculate_that(Two); 
     Thread.Sleep(10); 
     Calculate_thatThat(Three); 
     Thread.Sleep(10); 
     Update_lable_in_form(value); 
     Thread.Sleep(10); 
    } 
} 

: 같은

그래서 내 수업 보인다.

내 업데이트는 동시에 발생해야합니다 (적어도 동시에 발생하는 것 같습니다).

내 양식에 "계산"버튼을 사용자가 클릭, 내가 할 경우 :

Comp_func Func1_class = new Comp_func(); 
Comp_func Func2_class = new Comp_func(); 

Thread Func1_Thread = new Thread(() => Func1_class.Start_Test("Blah", 2,3)); 
Thread Func2_Thread = new Thread(() => Func2_class.Start_Test("BlahBlah", 4,5)); 

//Func1_Thread.Priority = ThreadPriority.Highest; /* Deleted after Comments */ 
    // Func2_Thread.Priority = ThreadPriority.Highest; /* Deleted after Comments */ 


Func1_Thread.Start(); 
Func2_Thread.Start(); 

/* 
    // Removed after Comments 

// Let only Threads Run 
while(true) 
{ 
    Application.DoEvent(); 
    Update(); 
} 

for(count = 0; count < 100; count++) 
{ 
    console.WriteLine("I WON'T USE WHILE(1) loops with DOEVENTS"); 
} 

*/ 

내 문제가 스레드 1이 완료의 실행, 그것은 Label를 업데이트 때 다음 2 시작을 끼운 것입니다 실행합니다.

이 문제를 피하기 위해 거의 각 줄 뒤에 Thread.Sleep();을 작성했습니다. 마치 윈도우가 전환을 돌보지 않은 것처럼 행동합니다!

왜 이런 일이 발생하는지 알고 싶습니다.

미리 감사드립니다.

+1

무슨 일이 일어날 예정입니까? 일반적으로 나쁜 습관으로 간주되는 몇 가지 사항에 대한 쪽지. 명시 적으로 스레드 우선 순위, 무한 루프를 나타냅니다. 왜 Thread.Sleep 라인이 필요한가요? – kaj

+0

내 문제는 스레드가 제대로 전환되지 않습니다. 실행은 스레드 1이 완료된 다음 스레드 2와 같습니다. 그래서 Thread.Sleep이 스레드를 전환하도록합니다. – Swanand

+1

스레드가 전환되지 않는다는 것을 어떻게 알 수 있습니까? 함수 호출에 따라 각 스레드에서 UI를 한 번만 업데이트합니다. 각 스레드가 작업을 완료하면 호출됩니다. 스레드 1이있는 코드는 스레드 2 이전에 항상 완료됩니다. – dice

답변

4

코드 예는 매우 불완전하므로 무슨 일이 일어나고 있는지보기가 어렵습니다. 당신이 귀하의 요구 사항 두 개의 라벨 업데이트에 대한 응답으로 모든

에서 while(true)..DoEvent() 코드를 필요가 없습니다 사실 - 내가 가진 것

첫 번째 의견은 당신이 당신의 클릭 핸들러에서 무한 루프가 없어야한다는 것입니다 동시에 가장 좋은 방법은 UI를 업데이트하기 전에 스레드가 합류하도록하는 것입니다.이 작업을 수행하는 한 가지 방법은 다른 두 스레드를 시작하는 BackgroundWorker를 작성한 다음 Join() 메소드를 사용하여 UI를 업데이트 한 후 두 개의 결과로 UI를 업데이트하는 것입니다. 실행중인 .net 버전에 따라 적은 수의 코드로 작업 라이브러리를 사용할 수 있습니다. @dice에 의해 제안

private void button1_Click(object sender, System.EventArgs e) 
    { 
     BackgroundWorker master= new BackgroundWorker(); 
     master.DoWork += (sender1, e1) => 
           { 
            Thread t1 = new Thread(Func1_class.Start_Test); 
            Thread t2 = new Thread(Func1_class.Start_Test); 
            t1.Start(); 
            t2.Start(); 
            t1.Join(); 
            t2.Join(); 
           }; 
     master.RunWorkerCompleted += (sender2, e2) => 
              { 
               label1.Text = "text"; 
               label2.Text = "text"; 
              }; 
     master.RunWorkerAsync(); 
    } 
+0

끔찍한 'DoEvents'루프를 해결하기위한 +1. –

+0

이것은 여러분에게 조건을 설명하기 위해 작성한 테스트 코드의 일종입니다. 그리고 일부 타이머 기능을 처리하고 스레드를 통해 양식을 업데이트하여 DoEvent() 및 Update()를 작성했습니다. ( – Swanand

+0

'일부 타이머 함수 처리'- Windows.Forms.Timers는 OnClick 처리기를 종료하면 올바르게 작동합니다. '폼을 통해 스레드 업데이트', (Invoke/BeginInvoke 사용), OnClick 처리기를 끝내면 그냥 잘 작동합니다. –

2

()를 호출하고 DoEvents() 루프, 수면 제거 : 여기

은 (당신이 사용할 수있는 태스크 라이브러리가없는 경우) 오히려 원유 구현 - 당신이 얼마나 생각하든 그들은 도움이되지 않습니다. 제대로 Invoke/BeginInvokeing을하면 레이블이 변경됩니다. 정상적으로 작동합니다. OnClick 이벤트 처리기를 종료하십시오. GUI 이벤트 핸들러에서 기다리지 않아야합니다.

반복 - GUI 이벤트 핸들러에서 기다리지 마십시오.

몇 개의 프로세서 코어가 있으며 왜 작업 스레드 우선 순위를 높이셨습니까? 하나의 CPU 만 있고 Func1_Thread에서 CPU를 많이 사용하는 작업을 시작하면 100 % CPU를 사용하여 자체가 멈출 때까지 계속 실행되거나 Windows anti-starvation 알고리즘은 30 초 후에 다른 스레드에 몇 가지주기를 제공합니다. 이것은 직렬화의 인상을 줄 것입니다.

높은 우선 순위로 스레드를 올린 다음 sleep() 호출을 삽입하는 것은 ... 음, 그냥하지 마십시오!

+0

제안 주셔서 감사합니다 ....이 기억할 것입니다!하지만 전환을위한 Thread.Sleep 삽입 한 ... 잠자고있는 한 스레드가 다른 스레드를 깨울 것 같았습니다 .... 우선 순위는 재판이었습니다 ... 그리고 듀얼 코어 3GHz 머신에서 실행됩니다! – Swanand

1

스레드에 대해 실제로 이해하지 못하는 것이 있습니다.

OS가 스레드 실행을 어떻게 처리하는지 알 수있는 방법이 없습니다. 레이블을 동시에 변경하려면 직접해야합니다.

예를 들어 super 함수가 끝나면 이벤트를 발생시킵니다. 예를 들어 SuperCalcDone이라고 부릅니다. SuperCalcDone 처리기에서 모든 계산이 완료되었는지 확인한 다음 레이블을 업데이트하십시오.

+0

제안 해 주셔서 감사합니다.하지만 업데이트를해야합니다 ... 그리고 또한 이 예제, 실제 코드에서 각 함수 다음에 거의 lables를 업데이트해야합니다. 또한 14 가지 함수가 있습니다. :(두 스레드가 독립 데이터를 처리하고 있습니다! – Swanand

관련 문제