2013-12-17 105 views
0

將靜態變量作爲計數器,可以通過C#.NET程序中的所有線程進行更新是否是一種很好的做法?
示例代碼:靜態變量和多線程

public class SomeTask 
{ 
static int count = 0; 
public void Process() 
{ 

    while(true) 
    { 
     //some repeated task 
     count++; 
     if(count>100000) 
     { 
      count=0; 
      break; 
     } 
    } 
} 
} 

public class WorkerRole : RoleEntryPoint 
{ 
    public override void Run() 
    { 
    while(true) 
    { 

     for (int i = 0; i < maxTasks; i++) 
     { 
      this.Tasks[i] = Task.Factory.StartNew(() => (new SomeTask()).Process()); 
     } 
     Task.WaitAll(this.Tasks); 

     //every 100000 in counter needs some updates at program level 
    } 
} 
} 
+2

除了已經作出的回答:這可能取決於你正在嘗試做的,恕我直言。 – Samuel

+0

有一個線程安全的「計數器」沒有好的做法 - 就像所有異步編程一樣,根據您要解決的問題,決策必須更加明瞭。根據你的情況,櫃檯可能是安全的,也可能不是。 –

+0

@Samuel更新了我的問題 – Seenu

回答

2

如果你不能避免它,那就沒問題。這是最好的使用Interlocked class增量計數器:

if (Interlocked.Increment(ref counter) % 100000 == 0) { 
    // Do something every hundred thousand times 
    // Use "== 1" if you also want to do it on the first iteration 
} 

我會留下下面的代碼的情況時,你只需要知道計數末

在你的情況,你可以保持count爲實例字段(即非靜態),增加公共getter和總結所有櫃檯後的所有任務已完成:

public class SomeTask 
{ 
    int count = 0; 
    public int Count { get { return count; } } 

    public void Process() 
    { 

     while(true) 
     { 
      //some repeated task 
      count++; 

      if (something) 
       break; 
     } 
    }   
} 

var someTasks = new List<SomeTask>(); 
for (int i = 0; i < maxTasks; i++) 
{ 
    var someTask = new SomeTask(); 
    someTasks.Add(someTask); 
    this.Tasks[i] = Task.Factory.StartNew(() => someTask.Process()); 
} 
Task.WaitAll(this.Tasks); 

// Your total count 
var total = someTasks.Sum(t => t.Counter); 
+0

你的回答在邏輯上是正確的,我的糟糕之處在於我以前沒有在我的問題中提供確切的要求。現在我更新了這個問題。 – Seenu

+0

我已經更新了我的答案,每100k次迭代執行一次操作。 –

0

,這是完全正確,只要你保持thread-safe和線程syncronized。您可以使用lock進行同步。你可以閱讀更多關於線程安全和靜態成員herehere。您也可以使用Interlocked.Increment以線程安全的方式增加計數器。在Eric Lippert answer處閱讀有關線程安全性的更多內容,

class Account 
{ 
    int count; 
    private Object thisLock = new Object(); 

    public void Add(decimal amount) 
    { 
     //your code 
     lock (thisLock) 
     { 
      count = count + 1; 
     } 
    } 
} 
+0

在計數只是遞增的情況下,說不需要鎖定是正確的。或者即使在這個操作中可能會出現「異常」? – tjheslin1

+1

我建議不要在這種情況下使用鎖定。鎖定可能非常昂貴,並且只是爲了增加計數器而進行鎖定可能會導致很多性能下降。 – Euphoric

+0

@Euphoric我的想法確切。 – tjheslin1

2

是的,這是一個很好的方法但要確保你使用一個原子類型。如果計數器遞增操作是使用線程安全代碼而不是原子操作來實現的,那麼我會擔心性能問題。

要實現一個計數器,您將使用++--。對於C#中的原始類型,這些通常不是線程安全的。

Is the ++ operator thread safe?

在C#中原子類型?

參見參考What operations are atomic in C#?

此答案提示,32位整數類型是在32臺機器上,64位整數類型是在64臺機器原子原子。