2014-10-15 2 views
2

여러 스레드에서 일부 작업을 수행하려고하지만 그 결과는 스레드를 관리하지 않아야합니다. 예를 들면 :여러 스레드에서 함수의 결과를 얻는 방법

이 코드에 의해
private void button1_Click(object sender, EventArgs e) 
    { 
     for (int j = 0; j < 2; j++) 
     { 
     ThreadPool.QueueUserWorkItem((o) => 
         { 
          var result = Function1(); 

          BeginInvoke(new Action(() => 
          { 
           Function2(result); 
          }) 
          ); 
         } 
      ); 
     } 

    } 

    private int Function1() 
    { 
     Random rnd = new Random(); 

     Thread.Sleep(1000); 
     int k = rnd.Next(10, 20); 
     return k; 
    } 

    private void Function2(int i) 
    { 
     string s = i.ToString(); 

     Thread.Sleep(2000); 

     s += i.ToString(); 

     MessageBox.Show(s); 
    } 

, Function1 여러 스레드에서 실행하고 function2()은 기능 1에서 결과를받은 후 결과 값 몇 가지 일을한다.

그러나 Function1()이 여러 스레드에서 실행될 때 result이 변경되었으므로 Function2은 결과가 무시되기 때문에 양호하게 작동하지 않습니다. 어떻게 해결할 수 있습니까? 배열에서 Function1의 반환 값을 저장하고 하나씩 관리해야한다고 생각합니다. 거기에 더 좋은 방법이 있습니까?

답변

3

배경 작업을 가능한 한 분리 된 상태로 유지하고 부작용을 피하는 데 많은 도움이됩니다.

그래서 Function1은 외부 상태를 변경하는 데 아무런 영향을 미치지 않아야하며 양식의 필드 또는 그 위치에 결과를 설정해서는 안됩니다. 수정하기가 쉽습니다.

따라서 Function1의 결과를 필드가 아닌 로컬 변수에 저장하십시오. 그런 다음 해당 변수를 Function2으로 전달하면 모두 완료됩니다.

ThreadPool.QueueUserWorkItem((o) => 
    { 
    var result = Function1(p1, p2, p3, p4, p5); 

    BeginInvoke(new Action(() => 
     { 
     Function2(result); 
     }) 
    ); 
    } 
); 

지금 당신의 배경 작업이 더 이상 공유 상태를 변경하고, 다른 곳에서 무슨 일이 생기면 병렬로 실행하는 것이 훨씬 안전하다 : 그 작업을 수행하는 한 가지 방법은 로컬 변수를 통해 클로저를 사용할 수 없습니다.

Function1이 다른 공유 상태를 변경하지 않는지 확인하십시오. 아, 그리고 심지어 Function1에있는 데이터를 읽을 때 조심하십시오 - 서로 다른 스레드에서 읽고 쓰고 있다면 일관성없는 데이터를 읽는 것은 매우 쉽습니다.

물론 이것은 멀티 스레딩 및 비동기 코드를 처리하는 오히려 오래된 방법입니다. .NET 4.5에 액세스 할 수 있다면 새로운 async/await 구문을 사용하는 것이 좋습니다. 이런 일 :는 (동기화 맥락 안에 더 정확하게 또는) 형태로 이벤트 핸들러 이렇게하면

var result = await Task.Run(() => return Function1(p1, p2, p3, p4, p5)); 

Function2(result); 

, 그것을 병렬 Function1을 실행하고, UI 스레드에 다시 결과 값을 푸시 할 , Function2에 대한 준비.

+0

작동하지 않았습니다. 결과는 마지막 것입니다. 다른 방법이 있습니까? – Elahe

+0

@Elahe 당신은 분명하지 않습니다. 마지막 하나? 이것은 단순히 백그라운드 작업으로 시작하는 각각의 결과에서'Function2'를 호출해야합니다. 그래서 마지막 결과 만 얻는다면 그것은'Function2' 메쏘드가 이전 결과를 덮어 쓰기 때문입니다. – Luaan

+0

귀하의 답변으로 제 질문을 편집합니다. 하지만 messageBox는 같은 값을 보여줍니다. – Elahe

관련 문제