2012-09-28 22 views
1

我看System.Threading.Tasks.TaskScheduler.Id實施的.NET 4.0,並請參閱下面的代碼:爲什麼msft比較Interlocked.Increment(ref uniqueId)爲零?

[__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()表示它返回遞增的值(遞增後),因此似乎不太合適以檢查零(除非您的計數器環繞,但如果發生這種情況,您有更大的問題,這些問題在這裏也沒有解決。)

如果我這樣做,我會簡單地做:

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他們這樣做。從Reference Source

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

感謝您指點我的官方參考! 似乎這個ID並不是真的意味着它是獨一無二的,這就是爲什麼我認爲他們不必關心環繞。謝謝! – JasonS

1

的不變是Id永遠不會返回0,因爲0在內部使用,以表明該值應該被初始化。如果Id曾經是0,那麼您下次查詢它時它將是一個不同的值。