Хотя класс Interlocked не предлагает этих методов, существует
хорошо известный шаблон, позволяющий выполнять любую операцию над
Int32 в < strong>атомарным способом с помощью Interlocked.CompareExchange.
Код: Выделить всё
public static Int32 Maximum(ref Int32 target, Int32 value)
{
Int32 currentVal = target, startVal, desiredVal;
// Don't access target in the loop except in an attempt
// to change it because another thread may be touching it
do
{
// Record this iteration's starting value
startVal = currentVal;
// Calculate the desired value in terms of startVal and value
desiredVal = Math.Max(startVal, value);
// NOTE: the thread could be preempted here!
// if (target == startVal) target = desiredVal
// Value prior to potential change is returned
currentVal = Interlocked.CompareExchange(ref target, desiredVal, startVal);
// If the starting value changed during this iteration, repeat
} while (startVal != currentVal);
// Return the maximum value when this thread tried to set it
return desiredVal;
}
Код: Выделить всё
[CompilerGenerated]
{
EventHandler eventHandler = this.MyEvent;
EventHandler eventHandler2;
do
{
eventHandler2 = eventHandler;
EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value);
eventHandler = Interlocked.CompareExchange(ref this.MyEvent, value2, eventHandler2);
}
while ((object)eventHandler != eventHandler2);
}
Исходный пример с использованием ref аргумент, что нужно сделать, чтобы предотвратить изменение целевого значения до того, как оно будет присвоено значению temp через:
Код: Выделить всё
Int32 currentVal = target, startVal, desiredVal;
РЕДАКТИРОВАТЬ: Вот пример того, что я среднее значение (стиль LINQPad)
Код: Выделить всё
void Main() {
var current = 33;
var otherThread = new Thread(() => MutateLocal(ref current));
otherThread.Start();
var result = Maximum(ref current, 55); // at this point current is 33
current.Dump(); // 100
result.Dump(); // 100
}
public static void MutateLocal(ref int target) {
Thread.Sleep(100);
target = 100;
}
public static Int32 Maximum(ref Int32 target, Int32 value) {
Console.WriteLine(target);
Thread.Sleep(200);
Console.WriteLine(target);
Int32 currentVal = target; // this is atomic...
// ... rest of the Maximum method from above
Подробнее здесь: https://stackoverflow.com/questions/785 ... threadsafe
Мобильная версия