2013-05-01 3 views
0

주어진 스레드가 어떤 이유로 실패하면 무한 루프가 발생하는 것으로 보입니다.병렬로 스레드를 실행하면 무한 루프가 발생하는 것 같습니다.

이 나에 의해 작성되지 않은 코드 그래서 심지어 을 편집 할 수는 있지만 여기에 가장 눈에 띄는 문제는, 카운터 변수 totalActions이 같은 휘발성 표시되지 않는다는 생각과 결과 스레드가 최신 값을보고 있지 않습니다.

totalActions의 실제 가치를 얻지 못하는 것처럼 보이므로 계속 기다리고 있을까요?

이로 인해 스레드가 재귀 적으로 실행됩니까? 디버깅하는 동안,

public void PerformActions(List<Action> actions) 
{ 
    object actionLock = new object(); 
    int totalActions = actionts.Count; 

    for(int x = 0; x < accounts.Count; x++) 
    { 
     int y = x; 
     new Thread(delegate() 
     { 
     actions[y].Invoke(); 

     if(Interlocked.Decrement(ref totalActions) == 0) 
     { 
      lock(actionLock) 
      { 
       Monitor.Pulse(actionLock); 
      } 
     } 
    }).Start(); 
    } 

    lock(actionLock) 
    { 
     if(totalActions > 0) 
     { 
      Monitor.Wait(actionLock); 
     }  
    } 
} 

업데이트

사용법이 같다 .... 내가 실행 스레드 (예외가 발생) 실패 통지하고, 그냥 반복해서 불렀다지고 유지하고, 여기서 myService은 API 서비스에서 json 요청을 가져 오기 위해 httpRequest 호출을 수행합니다.

Execute.InParallel(
new Action[] 
    { 
    () => { abc = myService.DoSomething(); }, 
    () => { def = myService.DoSomethingElse(); } 
    }); 
+1

이 코드처럼 할

올바른 방법은 TPL을 사용하여 처음에 기록되는이 잘못된 코드를 방지 한 것이 사실 이외의 TPL과 아무 (이 없습니다.) – dlev

+0

MSDN 문서에 따르면 휘발성의 사용은 전혀 사용하지 않으면 최소로 유지되어야합니다. 그리고 매우 제한된 메모리를 가진 임베디드 시스템에 주로 사용됩니다. 그들은'lock' 키워드 나 뮤텍스 나 세마포어 같은 잠금 메커니즘을 사용하는 것을 제안합니다. 또한'Interlocked.Decrement()'를 사용하면 처음부터 그 문제를 방지 할 수 있습니다. 이것이 원자 액션이기 때문에 한 번에 하나의 스레드 만 작업 할 수 있습니다. – Nomad101

+0

@ Nomad101 자바에서 알다시피 다른 스레드가 값을 볼 수 있도록 변수를 표시해야합니다. 그렇지 않으면 로컬 스레드 복사본이 사용되고 올바른 값이 아닐 수도 있습니다. C# 내의 – loyalflow

답변

0

자물쇠는 테스트 if(totalActions > 0) 현재 값을 읽어 보장, 메모리 장벽 역할을합니다. 나는이 규약이 경주에서 자유롭지는 못하지만 적어도 경주는 거의 없을 것이라고 확신한다. 당신은 그것을 재현하는데 어려움을 겪을 것입니다.

그래서 여기에 나와 있지 않은 문제가 있습니다. 디버거를 사용하여 관련된 스레드가 정확히 무엇을하는지 확인할 수 있습니까?

일부 스레드는 처리되지 않은 예외로 인해 사망한다고 말합니다. 일찍 종료 한 스레드가 카운트를 감소시키지 않을 수도 있습니다.

또한 코드를 변경할 수없는 경우 질문의 요점은 무엇입니까? 너에게 무엇을 제안해야할지 모르겠다.

+0

usr, thanaks, 예제 사용법을 알려주었습니다.이 myService가 api 호출을 호출하고 엔드 포인트가 다운되면 디버그 모드에서 계속 동일한 호출을 계속 반복합니다. DoSomething() – loyalflow

+0

암호. 디버깅하는 동안 내 브레이크 포인트가 Monitor.Wait 라인에 도달하면 실제로 감소하는 if 문에 도달하지 못하는 것으로 나타났습니다. 그것이 무한 루프의 원인입니까? NOt는 그것이 실패 할 때 httprequest를 만들려고 노력하는 이유를 확신합니다 ... – loyalflow

0

루프가 잘못되었습니다. 변수 x가 잘못 캡처되었습니다. actions[x].Invoke();이 각 스레드에서 실행될 때 항상 x의 마지막 값을가집니다. 따라서 배열에 전달 된 마지막 대리자는 여러 번 호출됩니다. 그것은이

for(int x = 0; x < accounts.Count; x++) 
     { 
      int y = x; // here correct value of y will be captured in delegate 
      new Thread(delegate() 
      { 
      actions[y].Invoke(); 
    ... 
+0

미안 해요. 실제 코드가 있었는데, 어떻게 든 미안합니다. – loyalflow

+0

그렇다면 가장 좋은 방법은 if ​​조건을 if (Interlocked.CompareExchange (ref totalActions, 0, 0)> 0)'로 변경하는 것입니다. – YK1

관련 문제