Reputation: 364
I'm writing a multi threaded application, where one part of the code must be thread safe to keep track of task numbers.
I have this method:
private void IncrementTaskNumber() {
Interlocked.Increment(ref _TaskNumber);
}
_TaskNumber is a private int in the same class. The problem is, this throws me a "A property, indexer or dynamic member access may not be passed as an out or ref parameter" exception. To get around this, I do:
private void IncrementTaskNumber() {
int _taskNum = _TaskNumber;
Interlocked.Increment(ref _taskNum);
_TaskNumber = _taskNum;
}
Is this still thread safe?
Upvotes: 1
Views: 223
Reputation: 62469
This is definitely not thread-safe:
private void IncrementTaskNumber() {
int _taskNum = _TaskNumber;
Interlocked.Increment(ref _taskNum);
_TaskNumber = _taskNum;
}
since a thread executing the sequence could be interrupted between each of these 3 operations. This won't work unless you introduce a loop that keeps retrying to increment if the local value changed in the meantime, but that would basically mean you are reimplementing Interlocked.Increment
using Interlocked.Increment
. :)
Just make _TaskNumber
a member variable, not a property.
Upvotes: 0
Reputation: 7515
You don't seem to have a locking mecanism in the IncrementTaskNumber
method. Unless you call it only from one place, it is not thread safe. The first implementation you wanted to do, even if it would have worked wouldn't have been either since Interlocked.Increment(ref _TaskNumber);
might have been called a second time before the first would have been done, and writen to the ref parameter.
Edit: If you want to make it threadsafe, you could modify yoru method like this :
private void IncrementTaskNumber()
{
lock (_TaskNumber)
_TaskNumber++;
}
Edit 2: (You might want to look into other solutions if using lock
is too costy for your application.)
Upvotes: 1
Reputation: 564861
_TaskNumber is a private int in the same class.
_TaskNumber
has to be a private field for this to work. You likely have it as a private property.
Define it as:
private int _TaskNumber;
And it will work.
Also note that your current workaround introduces a race condition - you're effectively getting rid of the atomic increment by doing it using a temporary variable, which defeats the purpose of using Interlocked
in the first place. You need to increment the field directly.
Upvotes: 3