Reputation: 2539
Is it a good practice to have a static variable as counter that can be updated by all the threads in a C#.NET program?
Sample Code:
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
}
}
}
Upvotes: 0
Views: 4063
Reputation: 21311
If you can't avoid it then it's fine. It's best to use Interlocked class increment the counter:
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
}
I'll leave the code below for the case when you only need to know the count at the end
In your case you could keep the count
as an instance field (i.e. non-static), add public getter and sum up all the counters after all tasks have finished:
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);
Upvotes: 2
Reputation: 148180
Yes, it is perfectly all right as long as you keep it thread-safe
and syncronized in threads. You can use lock for syncronization. You can read more about thread safety and static members here and here. You can also use Interlocked.Increment to increament the counter in a thread-safe way. Read more about thread safety with increament operator here in Eric Lippert answer.
class Account
{
int count;
private Object thisLock = new Object();
public void Add(decimal amount)
{
//your code
lock (thisLock)
{
count = count + 1;
}
}
}
Upvotes: 0
Reputation: 234875
Yes that is a good approach but make sure you use an atomic type. I would have performance concerns if the counter increment operations were implemented using thread safe code as opposed to atomic operations.
To implement a counter, you'll be making use of ++
and --
. These, in general, are not thread safe for the primitive types in C#.
See Is the ++ operator thread safe?
Atomic types in C#?
See reference What operations are atomic in C#?
This answer suggests that 32 bit integral types are atomic on 32 bit machines, 64 bit integral types are atomic on 64 bit machines.
Upvotes: 2