ThreadStaticAttribute ThreadStaticAttribute ThreadStaticAttribute ThreadStaticAttribute Class

定义

指示各线程的静态字段值是否唯一。Indicates that the value of a static field is unique for each thread.

public ref class ThreadStaticAttribute : Attribute
[System.AttributeUsage(System.AttributeTargets.Field, Inherited=false)]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public class ThreadStaticAttribute : Attribute
type ThreadStaticAttribute = class
    inherit Attribute
Public Class ThreadStaticAttribute
Inherits Attribute
继承
ThreadStaticAttributeThreadStaticAttributeThreadStaticAttributeThreadStaticAttribute
属性

示例

下面的示例实例化的随机数生成器,创建 10 个线程除了主线程,然后在每个线程中生成两个亿个随机数字。The following example instantiates a random number generator, creates ten threads in addition to the main thread, and then generates two million random numbers in each thread. 它使用ThreadStaticAttribute属性来计算每个线程的随机数字的个数和之和。It uses the ThreadStaticAttribute attribute to calculate the sum and the count of random numbers per thread. 它还定义了两个附加的每个线程字段previousabnormal,这样,以检测损坏的随机数生成器。It also defines two additional per-thread fields, previous and abnormal, that allows it to detect corruption of the random number generator.

using System;
using System.Threading;

public class Example
{
   [ThreadStatic] static double previous = 0.0;
   [ThreadStatic] static double sum = 0.0;
   [ThreadStatic] static int calls = 0;
   [ThreadStatic] static bool abnormal;
   static int totalNumbers = 0;
   static CountdownEvent countdown;
   private static Object lockObj;
   Random rand;
   
   public Example()
   { 
      rand = new Random();
      lockObj = new Object();
      countdown = new CountdownEvent(1);
   } 

   public static void Main()
   {
      Example ex = new Example();
      Thread.CurrentThread.Name = "Main";
      ex.Execute();
      countdown.Wait();
      Console.WriteLine("{0:N0} random numbers were generated.", totalNumbers);
   }

   private void Execute()
   {   
      for (int threads = 1; threads <= 10; threads++)
      {
         Thread newThread = new Thread(new ThreadStart(this.GetRandomNumbers));
         countdown.AddCount();
         newThread.Name = threads.ToString();
         newThread.Start();
      }
      this.GetRandomNumbers();
   }

   private void GetRandomNumbers()
   {
      double result = 0.0;
      
       
      for (int ctr = 0; ctr < 2000000; ctr++)
      {
         lock (lockObj) {
            result = rand.NextDouble();
            calls++;
            Interlocked.Increment(ref totalNumbers);
            // We should never get the same random number twice.
            if (result == previous) {
               abnormal = true;
               break;
            }
            else {
               previous = result;
               sum += result;
            }   
         }
      }
      // get last result
      if (abnormal)
         Console.WriteLine("Result is {0} in {1}", previous, Thread.CurrentThread.Name);
       
      Console.WriteLine("Thread {0} finished random number generation.", Thread.CurrentThread.Name);
      Console.WriteLine("Sum = {0:N4}, Mean = {1:N4}, n = {2:N0}\n", sum, sum/calls, calls);        
      countdown.Signal();
   }
}
// The example displays output similar to the following:
//    Thread 1 finished random number generation.
//    Total = 1,000,556.7483, Mean = 0.5003, n = 2,000,000
//    
//    Thread 6 finished random number generation.
//    Total = 999,704.3865, Mean = 0.4999, n = 2,000,000
//    
//    Thread 2 finished random number generation.
//    Total = 999,680.8904, Mean = 0.4998, n = 2,000,000
//    
//    Thread 10 finished random number generation.
//    Total = 999,437.5132, Mean = 0.4997, n = 2,000,000
//    
//    Thread 8 finished random number generation.
//    Total = 1,000,663.7789, Mean = 0.5003, n = 2,000,000
//    
//    Thread 4 finished random number generation.
//    Total = 999,379.5978, Mean = 0.4997, n = 2,000,000
//    
//    Thread 5 finished random number generation.
//    Total = 1,000,011.0605, Mean = 0.5000, n = 2,000,000
//    
//    Thread 9 finished random number generation.
//    Total = 1,000,637.4556, Mean = 0.5003, n = 2,000,000
//    
//    Thread Main finished random number generation.
//    Total = 1,000,676.2381, Mean = 0.5003, n = 2,000,000
//    
//    Thread 3 finished random number generation.
//    Total = 999,951.1025, Mean = 0.5000, n = 2,000,000
//    
//    Thread 7 finished random number generation.
//    Total = 1,000,844.5217, Mean = 0.5004, n = 2,000,000
//    
//    22,000,000 random numbers were generated.
Imports System.Threading

Public Class Example
   <ThreadStatic> Shared previous As Double = 0.0
   <ThreadStatic> Shared sum As Double = 0.0
   <ThreadStatic> Shared calls As Integer = 0
   <ThreadStatic> Shared abnormal As Boolean
   Shared totalNumbers As Integer = 0
   Shared countdown As CountdownEvent
   Private Shared lockObj As Object
   Dim rand As Random

   Public Sub New()
      rand = New Random()
      lockObj = New Object()
      countdown = New CountdownEvent(1)
   End Sub

   Public Shared Sub Main()
      Dim ex As New Example()
      Thread.CurrentThread.Name = "Main"
      ex.Execute()
      countdown.Wait()
      Console.WriteLine("{0:N0} random numbers were generated.", totalNumbers)
   End Sub

   Private Sub Execute()
      For threads As Integer = 1 To 10
         Dim newThread As New Thread(New ThreadStart(AddressOf GetRandomNumbers))
         countdown.AddCount()
         newThread.Name = threads.ToString()
         newThread.Start()
      Next
      Me.GetRandomNumbers()
   End Sub

   Private Sub GetRandomNumbers()
      Dim result As Double = 0.0
      
       
      For ctr As Integer = 1 To 2000000
         SyncLock lockObj
            result = rand.NextDouble()
            calls += 1
            Interlocked.Increment(totalNumbers)
            ' We should never get the same random number twice.
            If result = previous Then
               abnormal = True
               Exit For
            Else
               previous = result
               sum += result
            End If   
         End SyncLock
      Next
      ' Get last result.
      If abnormal Then
         Console.WriteLine("Result is {0} in {1}", previous, Thread.CurrentThread.Name)
      End If       
      
      Console.WriteLine("Thread {0} finished random number generation.", Thread.CurrentThread.Name)
      Console.WriteLine("Sum = {0:N4}, Mean = {1:N4}, n = {2:N0}", sum, sum/calls, calls)
      Console.WriteLine()        
      countdown.Signal()
   End Sub
End Class
' The example displays output similar to the following:
'    Thread 1 finished random number generation.
'    Total = 1,000,556.7483, Mean = 0.5003, n = 2,000,000
'    
'    Thread 6 finished random number generation.
'    Total = 999,704.3865, Mean = 0.4999, n = 2,000,000
'    
'    Thread 2 finished random number generation.
'    Total = 999,680.8904, Mean = 0.4998, n = 2,000,000
'    
'    Thread 10 finished random number generation.
'    Total = 999,437.5132, Mean = 0.4997, n = 2,000,000
'    
'    Thread 8 finished random number generation.
'    Total = 1,000,663.7789, Mean = 0.5003, n = 2,000,000
'    
'    Thread 4 finished random number generation.
'    Total = 999,379.5978, Mean = 0.4997, n = 2,000,000
'    
'    Thread 5 finished random number generation.
'    Total = 1,000,011.0605, Mean = 0.5000, n = 2,000,000
'    
'    Thread 9 finished random number generation.
'    Total = 1,000,637.4556, Mean = 0.5003, n = 2,000,000
'    
'    Thread Main finished random number generation.
'    Total = 1,000,676.2381, Mean = 0.5003, n = 2,000,000
'    
'    Thread 3 finished random number generation.
'    Total = 999,951.1025, Mean = 0.5000, n = 2,000,000
'    
'    Thread 7 finished random number generation.
'    Total = 1,000,844.5217, Mean = 0.5004, n = 2,000,000
'    
'    22,000,000 random numbers were generated.

该示例使用lockC# 中的语句和SyncLock构造在 Visual Basic 中的随机数字生成器对访问进行同步。The example uses the lock statement in C# and the SyncLock construct in Visual Basic to synchronize access to the random number generator. 这可以防止损坏的随机数生成器,这通常会在其返回值为零的所有后续调用。This prevents corruption of the random number generator, which typically results in its returning a value of zero for all subsequent calls.

此示例还使用CountdownEvent类,以确保每个线程已完成生成随机数字,然后再显示的调用总数。The example also uses the CountdownEvent class to ensure that each thread has finished generating random numbers before it displays the total number of calls. 否则,如果主线程完成之前它会生成的其他线程的执行,它会显示方法调用的总数不准确的值。Otherwise, if the main thread completes execution before the additional threads that it spawns, it displays an inaccurate value for the total number of method calls.

注解

一个static字段标记有ThreadStaticAttribute线程间不共享。A static field marked with ThreadStaticAttribute is not shared between threads. 每个执行线程具有单独的实例的字段中,独立设置并为该字段获取值。Each executing thread has a separate instance of the field, and independently sets and gets values for that field. 如果在另一个线程访问该字段,则它将包含不同的值。If the field is accessed on a different thread, it will contain a different value.

请注意,除了应用ThreadStaticAttribute属性到字段,还必须定义其作为static字段 (在 C# 中) 或Shared字段 (在 Visual Basic)。Note that in addition to applying the ThreadStaticAttribute attribute to a field, you must also define it as a static field (in C#) or a Shared field (in Visual Basic).

备注

请勿为使用标记字段指定初始值ThreadStaticAttribute,因为只有一次,当类构造函数执行,并因此影响只有一个线程将发生此类初始化。Do not specify initial values for fields marked with ThreadStaticAttribute, because such initialization occurs only once, when the class constructor executes, and therefore affects only one thread. 如果不指定一个初始值,您可以借助正在初始化为其默认值,如果它是值类型,或该字段null如果它是引用类型。If you do not specify an initial value, you can rely on the field being initialized to its default value if it is a value type, or to null if it is a reference type.

使用此属性,因为它是,和从其派生。Use this attribute as it is, and do not derive from it.

有关使用属性的详细信息,请参阅属性For more information about using attributes, see Attributes.

构造函数

ThreadStaticAttribute() ThreadStaticAttribute() ThreadStaticAttribute() ThreadStaticAttribute()

初始化 ThreadStaticAttribute 类的新实例。Initializes a new instance of the ThreadStaticAttribute class.

方法

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

返回一个值,该值指示此实例是否与指定的对象相等。Returns a value that indicates whether this instance is equal to a specified object.

(Inherited from Attribute)
GetHashCode() GetHashCode() GetHashCode() GetHashCode()

返回此实例的哈希代码。Returns the hash code for this instance.

(Inherited from Attribute)
GetType() GetType() GetType() GetType()

获取当前实例的 TypeGets the Type of the current instance.

(Inherited from Object)
IsDefaultAttribute() IsDefaultAttribute() IsDefaultAttribute() IsDefaultAttribute()

在派生类中重写时,指示此实例的值是否是派生类的默认值。When overridden in a derived class, indicates whether the value of this instance is the default value for the derived class.

(Inherited from Attribute)
Match(Object) Match(Object) Match(Object) Match(Object)

当在派生类中重写时,返回一个指示此实例是否等于指定对象的值。When overridden in a derived class, returns a value that indicates whether this instance equals a specified object.

(Inherited from Attribute)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

创建当前 Object 的浅表副本。Creates a shallow copy of the current Object.

(Inherited from Object)
ToString() ToString() ToString() ToString()

返回表示当前对象的字符串。Returns a string that represents the current object.

(Inherited from Object)

显式界面实现

_Attribute.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr) _Attribute.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr) _Attribute.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr) _Attribute.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr)

将一组名称映射为对应的一组调度标识符。Maps a set of names to a corresponding set of dispatch identifiers.

(Inherited from Attribute)
_Attribute.GetTypeInfo(UInt32, UInt32, IntPtr) _Attribute.GetTypeInfo(UInt32, UInt32, IntPtr) _Attribute.GetTypeInfo(UInt32, UInt32, IntPtr) _Attribute.GetTypeInfo(UInt32, UInt32, IntPtr)

检索对象的类型信息,然后可以使用该信息获取接口的类型信息。Retrieves the type information for an object, which can be used to get the type information for an interface.

(Inherited from Attribute)
_Attribute.GetTypeInfoCount(UInt32) _Attribute.GetTypeInfoCount(UInt32) _Attribute.GetTypeInfoCount(UInt32) _Attribute.GetTypeInfoCount(UInt32)

检索对象提供的类型信息接口的数量(0 或 1)。Retrieves the number of type information interfaces that an object provides (either 0 or 1).

(Inherited from Attribute)
_Attribute.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr) _Attribute.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr) _Attribute.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr) _Attribute.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr)

提供对某一对象公开的属性和方法的访问。Provides access to properties and methods exposed by an object.

(Inherited from Attribute)

属性

TypeId TypeId TypeId TypeId

在派生类中实现时,获取此 Attribute 的唯一标识符。When implemented in a derived class, gets a unique identifier for this Attribute.

(Inherited from Attribute)

适用于

另请参阅