2012-08-27 4 views
1

코드의 한 부분이 작업 번호를 추적하기 위해 스레드 안전해야하는 다중 스레드 응용 프로그램을 작성하고 있습니다.다중 스레드 응용 프로그램에서 작업 번호 추적

나는이 방법이 있습니다

private void IncrementTaskNumber() { 
    Interlocked.Increment(ref _TaskNumber); 
} 

_TaskNumber는 같은 클래스에있는 사립 INT이다. 문제는 이것이 나에게 "속성, 인덱서 또는 동적 멤버 액세스가 out 또는 ref 매개 변수로 전달되지 않을 수 있습니다"예외를 던졌습니다. 이 해결하기 위해, 내가 할 :

private void IncrementTaskNumber() { 
    int _taskNum = _TaskNumber; 
    Interlocked.Increment(ref _taskNum); 
    _TaskNumber = _taskNum; 
} 

이 여전히 스레드 안전 있습니까?

+0

'_TaskNumber' 선언문을 보여주십시오. 오류 메시지가 주어지면'private int _TaskNumber {get; 세트; }'- 그게 맞습니까? –

+0

@ Reduce Copsey, 예 private int _TaskNumber {get; set;} – ThomasVestergaard

+0

개인 속성이 아닌 필드를 사용해야합니다. 자세한 내용은 내 대답을 참조하십시오. –

답변

3

_TaskNumber는 동일한 클래스의 개인 int입니다.

_TaskNumber

이 작동 할 개인 필드 수 있습니다. 당신은 사유지로 생각할 것입니다.

는로 정의합니다

private int _TaskNumber; 

그리고 그것은 작동합니다.

또한 현재 해결 방법은 경쟁 조건을 도입합니다. 즉, 처음에는 Interlocked을 사용하는 목적을 무효로하는 임시 변수를 사용하여 원자 증가분을 효과적으로 제거 할 수 있습니다. 필드를 직접 증가시켜야합니다.

+0

고마워.예상 tham이 더 쉽다 :) – ThomasVestergaard

1

IncrementTaskNumber 메쏘드에 잠금 장치가없는 것 같습니다. 한 곳에서만 호출하지 않는 한 스레드로부터 안전하지 않습니다. Interlocked.Increment(ref _TaskNumber);은 첫 번째 작업이 완료되기 전에 두 번째 호출되어 ref 매개 변수에 기록되기 때문에 작업하지 않았더라도 수행하려는 첫 번째 구현은 없었을 것입니다. 당신이 yoru 방법을 다음과 같이 수정할 수 당신이 스레드 안전 확인하려면 : 편집

private void IncrementTaskNumber() 
{ 
    lock (_TaskNumber) 
     _TaskNumber++; 
} 

편집 2 : (lock를 사용하는 사용자 너무 costy 경우 당신은 다른 솔루션에보고 할 수 있습니다 응용 프로그램)

+0

잠금을 사용하여 작업 당 하나의 증가분을 수행하는 것이 너무 비싸다면, 아마도 더 큰 문제가있을 것이다. – Servy

+0

@Servy 작은 작업 기관에서는 잠금 장치가 매우 비싸게 보일 수 있습니다. 그 이유로 TPL에 엄청난 양의 배관이 있습니다. –

+0

@ReedCopsey 루프에서 자주 수행해야하는 작업이라면 동의합니다. 단 한 번만 완료되었으므로 작업 당 실제 문제라면 그 작업 단위가 너무 작아서 너무 많은 작업을 수행했다는 것을 의미합니다. – Servy

0

이 확실히하지 스레드 안전 :.

private void IncrementTaskNumber() { 
    int _taskNum = _TaskNumber; 
    Interlocked.Increment(ref _taskNum); 
    _TaskNumber = _taskNum; 
} 

순서를 실행하는 스레드가 중단 될 수 있기 때문에 각각의 3 가지 작업 사이. 그 동안 로컬 값이 변경되면 증가하기를 계속 반복하는 루프를 도입하지 않으면 이것이 작동하지 않지만 기본적으로 Interlocked.Increment을 다시 구현한다는 것을 의미합니다. Interlocked.Increment을 사용합니다. :)

단지 _TaskNumber구성원 변수가 아니라 속성.

관련 문제