2017-11-30 13 views
-2

루프에 Parallel.Foreach 루프에 문제가 있습니다. 오랫동안 부모 GUI 프로그램의 Progressbar Value를 증가시키는 방법을 호출하지 않아야합니다. KeinPapierVersand은 간단한 List<int> 개체이고 EinzelnachweisDruckDatumDateTime입니다.Parallel.Foreach는 Invoke를 사용하여 유휴 상태로 시작합니다.

Parallel.ForEach(KeinPapierVersand, partner => 
{ 
    generate_PCL_nachweis(partner, EinzelnachweisDruckDatum, true, false); 
    generate_BGF_Report(partner, EinzelnachweisDruckDatum, false); 

    //If the following line is uncommented, the loop starts to idle after about 200 
    // processed Items and will never reach the code after the loop. 

    myProgressbar_einzelnachweis_druck.Parent.BeginInvoke(new MethodInvoker(delegate 
    { 
     myProgressbar_einzelnachweis_druck.Value = 
             myProgressbar_einzelnachweis_druck.Value + 1; 
    })); 
}); 

이들은 C#에서 병렬 처리가되는 첫 번째 단계입니다. 나는 여기에 어떤 문제가 있는지 아무 단서도 없다. 예외는 던져지지 않았다. (전에 Try/Catch에 넣었다.) 진행 표시 줄이 호출되지 않으면 루프가 항상 문제없이 끝납니다. 왜 논리가 작동하지 않습니까? 추론의 오류는 어디에 있습니까? 도와주세요.

EDIT : 여기서 문제는 교착 상태입니다. 아래에서 완벽하게 아론이 설명합니다. 처리하고자하는 전체 작업 부하를 배경 작업자로 지정합니다. 이것은 완벽하게 작동합니다.

답변

3

대부분의 경우 UI UI 스레드에서 Parallel.ForEach 메서드를 호출하고 있습니다. 버튼 클릭이나 기타 UI 이벤트에 대한 응답으로 이 경우 Parallel.ForEach 행 자체가 기본 UI 스레드에서 실행되고 요청한 동시 작업이 완료 될 때까지 대기하는 기본 스레드를 차단합니다.

Invoke() 작동 방식은 메시지를 기본 UI 스레드로 보내고 메시지 처리를 기다리는 것입니다. 처리가 완료되면 돌아가고 진행이 계속됩니다. 코드에서 스레드가 Invoke()를 호출하면 Invoke가 완료 될 때까지 대기합니다. 그러나 주 스레드가 Parallel.ForEach에 의해 차단되고 Parallel.ForEach가 완료 될 때까지 진행률 막대를 업데이트하라는 요청을 처리 할 수 ​​없기 때문에 Invoke가 완료되지 않습니다. 그것은 교착 상태 유형입니다.

이 문제를 해결하는 데는 여러 가지 방법이 있습니다. 그것들은 모두 본질적으로 Parallel.ForEach를 주 스레드로부터 떼어 내기에 충분합니다. 이 작업을 수행하는 가장 간단한 방법 중 하나는 코드 샘플이 충분하지 않아서 async/await을 사용하여 작업을 시작한 다음 Parallel.ForEach를 호출하고 결과를 기다리는 것입니다. 이렇게하면 진행률 표시 줄 업데이트를 처리 할 수 ​​있도록 기본 스레드가 비워집니다.

작업이 완료되면 BeginInvoke는 주 스레드가 메시지를 완료하기 전에 처리 할 때까지 기다리지 않기 때문에 Invoke 대신 BeginInvoke를 사용하여 여기로 전환하는 것을 고려할 수 있습니다. 업데이트 순서가 보장되지 않고 ForEach가 완료된 후에도 업데이트가 발생할 수 있기 때문에 사용하기가 다소 까다 롭습니다. 루트 문제를 해결할 수는 없지만 먼저 해결해야합니다. Invoke() 버전이 실제로 병렬 루프의 속도를 늦추므로 더 효율적입니다.

+0

귀하의 상세하고 매우 명확한 설명에 감사드립니다. 그래서 이것은 고전적인 데드 록 상황입니다. 나는 몇 가지 방법을 시도하고 그에 따라 내 대답을 업데이 트됩니다. – kurdy