2012-09-28 1 views
1

나는 .NET 4.0의 System.Threading.Tasks.TaskScheduler.Id 구현을보고, 다음 코드를 참조하고 있습니다 :msft에서 Interlocked.Increment (ref uniqueId)를 0으로 비교하는 이유는 무엇입니까?

[__DynamicallyInvokable] 
public int Id 
{ 
    [__DynamicallyInvokable] 
    get 
    { 
     if (this.m_taskSchedulerId == 0) 
     { 
      int num = 0; 
      do 
      { 
       num = Interlocked.Increment(ref s_taskSchedulerIdCounter); 
      } 
      while (num == 0); 
      Interlocked.CompareExchange(ref this.m_taskSchedulerId, num, 0); 
     } 
     return this.m_taskSchedulerId; 
    } 
} 

왜 MSFT (가) 연동 이후의 num == 0을 비교 않습니다를? Interlocked.Increment()의 구현은 증가 후 값을 반환하므로 0을 확인하는 것이 비현실적인 것으로 나타납니다 (카운터가 래핑되지 않는 한 그런 일이 발생하면 여기에서도 해결되지 않은 더 큰 문제가 있음)

내가 할 것 인 경우에, 나는 간단하게 할 거라고 :

public int Id 
     { 
      get 
      { 
       if(m_taskSchedulerId==0) 
       { 
        var result = Interlocked.Increment(ref s_taskSchedulerIdCounter); 
        Interlocked.CompareExchange(ref m_taskSchedulerId, result, 0); 
       } 
       return m_taskSchedulerId; 
      } 
     } 
+2

아마 "벨트 및 중괄호"접근 방식 일 수 있습니다. 반환 값이 어떤 식 으로든 0이면 다음에'Id '가 액세스 될 때'Id'가 다시 생성되고 (이번에는 0이 아닌 경우) -'Id'가 변경됩니다. –

답변

8

하지만이 발생하는 경우가 더 큰 문제

없음

을 가지고, 그 정확한 reaso입니다 n 그들은 이것을한다. Reference Source에서 0의 값을 초기화해야 함을 표시하기 위해 내부적으로 사용되기 때문에

public Int32 Id 
{ 
    get 
    { 
     if (m_taskSchedulerId == 0) 
     { 
      int newId = 0; 

      // We need to repeat if Interlocked.Increment wraps around and returns 0. 
      // Otherwise next time this scheduler's Id is queried it will get a new value 
      do 
      { 
       newId = Interlocked.Increment(ref s_taskSchedulerIdCounter); 
      } while (newId == 0); 

      Interlocked.CompareExchange(ref m_taskSchedulerId, newId, 0); 
     } 

     return m_taskSchedulerId; 
    } 
} 
+0

나를 공식적인 참고서로 안내해 주셔서 감사합니다! 이드는 진정으로 고유 한 의미가 아니라고 생각합니다. 그래서 내가 랩을 신경 쓰지 않아야한다고 생각한 것입니다. 감사! – JasonS

1

불변는 Id 결코 0을 반환하지 않는다는 것이다. Id이 0 인 경우 다음 번 쿼리했을 때 다른 값이됩니다.

관련 문제