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
Атрибуты

Примеры

Следующий пример создает экземпляр генератора случайных чисел, создает десяти потоков в дополнение к основной поток и затем создает два миллиона случайных чисел в каждом потоке.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. Он также определяет два поля дополнительный поток, previous и abnormal, которое позволяет обнаружить повреждение генератора случайных чисел.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.

В примере используется lock инструкции на языке C# и 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()

Возвращает объект Type для текущего экземпляра.Gets 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)

Применяется к

Дополнительно