Interlocked.Decrement Method (Int32%)
Microsoft Silverlight will reach end of support after October 2021. Learn more.
Decrements a specified 32-bit signed integer variable and stores the result, as an atomic operation.
Namespace: System.Threading
Assembly: mscorlib (in mscorlib.dll)
Syntax
'Declaration
Public Shared Function Decrement ( _
ByRef location As Integer _
) As Integer
public static int Decrement(
ref int location
)
Parameters
- location
Type: System.Int32%
The variable whose value is to be decremented.
Return Value
Type: System.Int32
The decremented value.
Remarks
This method handles an overflow condition by wrapping: If location = Int32.MinValue, location - 1 = Int32.MaxValue. No exception is thrown.
Examples
The following example shows a thread-safe way to increment and decrement an integer value. The example defines CountClass, a class that keeps a running count of its instances by incrementing a counter in the constructor and decrementing the counter in the finalizer. Two counts are kept, one that uses standard addition and subtraction, and one that uses Increment and Decrement.
The example creates two threads, each of which creates and releases a large number of CountClass instances. After a garbage collection has been forced to clean up all the instances, both counts should be zero. SafeInstanceCount, which uses the Interlocked methods, will always be zero. However, UnsafeInstanceCount will not necessarily be zero because addition and subtraction are not atomic on fields: The count must be fetched, incremented, and then stored. A thread can be preempted in the middle of the increment or decrement operation — for example, after it has loaded and incremented the count, but before the new value has been stored. While the thread is preempted, the other thread can increment the count, or the finalizer thread can decrement the count. When the first thread continues running and stores its new value, it wipes out the operations that occurred while it was preempted. This program magnifies that effect because it does nothing but create instances, so that many instances of CountClass could be created while a thread is preempted.
In addition, on a multiprocessor computer two threads can be performing an operation simultaneously. Both can fetch the same value, increment it, and store it, so that the count is increased by one even though two instances are created.
Note: |
---|
To run this example, see Building Examples That Use a Demo Method and a TextBlock Control. |
Imports System.Threading
Public Class Example
Private Shared outputBlock As System.Windows.Controls.TextBlock
Public Shared Sub Demo(ByVal outputBlock As System.Windows.Controls.TextBlock)
Example.outputBlock = outputBlock
Dim t As New Thread(AddressOf DemoThreadProc)
t.Start()
End Sub
Private Shared Sub DemoThreadProc()
' Start two threads that will create/destroy a large number of CountClass
' objects, and block until the thread finish.
Dim thread1 As New Thread(AddressOf ThreadMethod)
Dim thread2 As New Thread(AddressOf ThreadMethod)
thread1.Start()
thread2.Start()
thread1.Join()
thread2.Join()
' Have the garbage collector run the finalizer for each
' instance of CountClass and wait for it to finish.
GC.Collect()
GC.WaitForPendingFinalizers()
outputBlock.Dispatcher.BeginInvoke(displayHelper, _
String.Format( _
"After garbage collection has occurred for all instances of CountClass," & vbLf _
& "the instance count should be zero." & vbLf & vbLf _
& "UnsafeInstanceCount: {0}" & vbLf & "SafeInstanceCount: {1}", _
CountClass.UnsafeInstanceCount, _
CountClass.SafeInstanceCount))
End Sub
Private Shared Sub ThreadMethod()
Dim cClass As CountClass
' Create 100,000 instances of CountClass.
For i As Integer = 1 To 100000
cClass = New CountClass()
Next i
End Sub
' Helper methods:
' In order to update the TextBlock object, which is on the UI thread, you must
' make a cross-thread call by using the Dispatcher object that is associated
' with the TextBlock. The DisplayOutput helper method and its delegate,
' displayHelper, are used by the BeginInvoke method of the Dispatcher object
' to append text to the TextBlock.
'
Private Shared displayHelper As New Action(Of String)(AddressOf DisplayOutput)
Private Shared Sub DisplayOutput(ByVal msg As String)
outputBlock.Text &= msg
End Sub
End Class
Public Class CountClass
Shared unsafeCount As Integer = 0
Shared safeCount As Integer = 0
Shared ReadOnly Property UnsafeInstanceCount() As Integer
Get
Return unsafeCount
End Get
End Property
Shared ReadOnly Property SafeInstanceCount() As Integer
Get
Return safeCount
End Get
End Property
Sub New()
unsafeCount += 1
Interlocked.Increment(safeCount)
End Sub
Protected Overrides Sub Finalize()
unsafeCount -= 1
Interlocked.Decrement(safeCount)
MyBase.Finalize()
End Sub
End Class
' This example produces output similar to the following:
'
'After garbage collection has occurred for all instances of CountClass,
'the instance count should be zero.
'
'UnsafeInstanceCount: -305
'SafeInstanceCount: 0
using System;
using System.Threading;
class Example
{
private static System.Windows.Controls.TextBlock outputBlock;
public static void Demo(System.Windows.Controls.TextBlock outputBlock)
{
Example.outputBlock = outputBlock;
Thread t = new Thread(DemoThreadProc);
t.Start();
}
private static void DemoThreadProc()
{
// Start two threads that will create/destroy a large number of CountClass
// objects, and block until the thread finish.
Thread thread1 = new Thread(new ThreadStart(ThreadMethod));
Thread thread2 = new Thread(new ThreadStart(ThreadMethod));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
// Have the garbage collector run the finalizer for each
// instance of CountClass and wait for it to finish.
GC.Collect();
GC.WaitForPendingFinalizers();
outputBlock.Dispatcher.BeginInvoke(delegate () {
outputBlock.Text += String.Format(
"After garbage collection has occurred for all instances of CountClass,\n"
+ "the instance count should be zero.\n\n"
+ "UnsafeInstanceCount: {0}\nSafeInstanceCount: {1}\n",
CountClass.UnsafeInstanceCount,
CountClass.SafeInstanceCount);
});
}
static void ThreadMethod()
{
CountClass cClass;
// Create 100,000 instances of CountClass.
for (int i = 0; i < 100000; i++)
{
cClass = new CountClass();
}
}
}
class CountClass
{
static int unsafeInstanceCount = 0;
static int safeInstanceCount = 0;
static public int UnsafeInstanceCount
{
get { return unsafeInstanceCount; }
}
static public int SafeInstanceCount
{
get { return safeInstanceCount; }
}
public CountClass()
{
unsafeInstanceCount++;
Interlocked.Increment(ref safeInstanceCount);
}
~CountClass()
{
unsafeInstanceCount--;
Interlocked.Decrement(ref safeInstanceCount);
}
}
/* This example produces output similar to the following:
After garbage collection has occurred for all instances of CountClass,
the instance count should be zero.
UnsafeInstanceCount: -292
SafeInstanceCount: 0
*/
Version Information
Silverlight
Supported in: 5, 4, 3
Silverlight for Windows Phone
Supported in: Windows Phone OS 7.1, Windows Phone OS 7.0
XNA Framework
Supported in: Xbox 360, Windows Phone OS 7.0
Platforms
For a list of the operating systems and browsers that are supported by Silverlight, see Supported Operating Systems and Browsers.
See Also