Monitor Klasse

Definition

Stellt einen Mechanismus bereit, der den Zugriff auf Objekte synchronisiert.Provides a mechanism that synchronizes access to objects.

public ref class Monitor abstract sealed
[System.Runtime.InteropServices.ComVisible(true)]
public static class Monitor
type Monitor = class
Public Class Monitor
Vererbung
Monitor
Attribute

Beispiele

Im folgenden Beispiel wird die Monitor -Klasse verwendet, um den Zugriff auf eine einzelne Instanz eines Zufallszahlengenerators zu Random synchronisieren, der durch die-Klasse dargestellt wird.The following example uses the Monitor class to synchronize access to a single instance of a random number generator represented by the Random class. Im Beispiel werden zehn Aufgaben erstellt, von denen jede asynchron in einem Thread Pool Thread ausgeführt wird.The example creates ten tasks, each of which executes asynchronously on a thread pool thread. Jede Aufgabe generiert 10.000 Zufallszahlen, berechnet ihren Durchschnitt und aktualisiert zwei Variablen auf Prozedur Ebene, die eine laufende Gesamtzahl der generierten Zufallszahlen und deren Summe beibehalten.Each task generates 10,000 random numbers, calculates their average, and updates two procedure-level variables that maintain a running total of the number of random numbers generated and their sum. Nachdem alle Tasks ausgeführt wurden, werden diese beiden Werte verwendet, um den allgemeinen Mittelwert zu berechnen.After all tasks have executed, these two values are then used to calculate the overall mean.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      List<Task> tasks = new List<Task>();
      Random rnd = new Random();
      long total = 0;
      int n = 0;
      
      for (int taskCtr = 0; taskCtr < 10; taskCtr++)
         tasks.Add(Task.Run( () => {  int[] values = new int[10000];
                                      int taskTotal = 0;
                                      int taskN = 0;
                                      int ctr = 0;
                                      Monitor.Enter(rnd);
                                         // Generate 10,000 random integers
                                         for (ctr = 0; ctr < 10000; ctr++)
                                            values[ctr] = rnd.Next(0, 1001);
                                      Monitor.Exit(rnd);
                                      taskN = ctr;
                                      foreach (var value in values)
                                         taskTotal += value;

                                      Console.WriteLine("Mean for task {0,2}: {1:N2} (N={2:N0})",
                                                        Task.CurrentId, (taskTotal * 1.0)/taskN,
                                                        taskN);
                                      Interlocked.Add(ref n, taskN);
                                      Interlocked.Add(ref total, taskTotal);
                                    } ));
      try {
         Task.WaitAll(tasks.ToArray());
         Console.WriteLine("\nMean for all tasks: {0:N2} (N={1:N0})",
                           (total * 1.0)/n, n);

      }
      catch (AggregateException e) {
         foreach (var ie in e.InnerExceptions)
            Console.WriteLine("{0}: {1}", ie.GetType().Name, ie.Message);
      }
   }
}
// The example displays output like the following:
//       Mean for task  1: 499.04 (N=10,000)
//       Mean for task  2: 500.42 (N=10,000)
//       Mean for task  3: 499.65 (N=10,000)
//       Mean for task  8: 502.59 (N=10,000)
//       Mean for task  5: 502.75 (N=10,000)
//       Mean for task  4: 494.88 (N=10,000)
//       Mean for task  7: 499.22 (N=10,000)
//       Mean for task 10: 496.45 (N=10,000)
//       Mean for task  6: 499.75 (N=10,000)
//       Mean for task  9: 502.79 (N=10,000)
//
//       Mean for all tasks: 499.75 (N=100,000)
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim tasks As New List(Of Task)()
      Dim rnd As New Random()
      Dim total As Long = 0
      Dim n As Integer = 0

      For taskCtr As Integer = 0 To 9
         tasks.Add(Task.Run( Sub()
                                Dim values(9999) As Integer
                                Dim taskTotal As Integer = 0
                                Dim taskN As Integer = 0
                                Dim ctr As Integer = 0
                                Monitor.Enter(rnd)
                                   ' Generate 10,000 random integers.
                                    For ctr = 0 To 9999
                                       values(ctr) = rnd.Next(0, 1001)
                                    Next
                                Monitor.Exit(rnd)
                                taskN = ctr
                                For Each value in values
                                   taskTotal += value
                                Next
                                    
                                Console.WriteLine("Mean for task {0,2}: {1:N2} (N={2:N0})",
                                                  Task.CurrentId, taskTotal/taskN,
                                                  taskN)
                                Interlocked.Add(n, taskN)
                                Interlocked.Add(total, taskTotal)
                             End Sub ))
      Next
      
      Try
         Task.WaitAll(tasks.ToArray())
         Console.WriteLine()
         Console.WriteLine("Mean for all tasks: {0:N2} (N={1:N0})",
                           (total * 1.0)/n, n)
      Catch e As AggregateException
         For Each ie In e.InnerExceptions
            Console.WriteLine("{0}: {1}", ie.GetType().Name, ie.Message)
         Next
      End Try
   End Sub
End Module
' The example displays output like the following:
'       Mean for task  1: 499.04 (N=10,000)
'       Mean for task  2: 500.42 (N=10,000)
'       Mean for task  3: 499.65 (N=10,000)
'       Mean for task  8: 502.59 (N=10,000)
'       Mean for task  5: 502.75 (N=10,000)
'       Mean for task  4: 494.88 (N=10,000)
'       Mean for task  7: 499.22 (N=10,000)
'       Mean for task 10: 496.45 (N=10,000)
'       Mean for task  6: 499.75 (N=10,000)
'       Mean for task  9: 502.79 (N=10,000)
'
'       Mean for all tasks: 499.75 (N=100,000)

Da auf Sie von jeder Aufgabe aus zugegriffen werden kann, die in einem Thread Pool Thread ausgeführt wird total , n muss der Zugriff auf die Variablen und ebenfalls synchronisiert werden.Because they can be accessed from any task running on a thread pool thread, access to the variables total and n must also be synchronized. Zu Interlocked.Add diesem Zweck wird die-Methode verwendet.The Interlocked.Add method is used for this purpose.

Im folgenden Beispiel Monitor wird die kombinierte Verwendung der-Klasse (implementiert mit dem lock -oder SyncLock -Sprachkonstrukt) Interlocked , der-Klasse AutoResetEvent und der-Klasse veranschaulicht.The following example demonstrates the combined use of the Monitor class (implemented with the lock or SyncLock language construct), the Interlocked class, and the AutoResetEvent class. Im Beispiel werden zwei internal- (in C#) oder Friend-Klassen (in Visual Basic), SyncResource und UnSyncResource, definiert, die entsprechend synchronisierten und nicht synchronisierten Zugriff auf eine Ressource bereitstellen.It defines two internal (in C#) or Friend (in Visual Basic) classes, SyncResource and UnSyncResource, that respectively provide synchronized and unsynchronized access to a resource. Damit sichergestellt ist, dass der Unterschied zwischen dem synchronisierten und dem nicht synchronisierten Zugriff im Beispiel deutlich wird (was der Fall sein kann, wenn jeder Methodenaufruf schnell abgeschlossen wird), enthält die Methode eine zufällige Verzögerung: Für Threads, deren Thread.ManagedThreadId-Eigenschaft einen geraden Wert hat, ruft die Methode die Thread.Sleep-Methode auf, um eine Verzögerung von 2.000 Millisekunden einzuführen.To ensure that the example illustrates the difference between the synchronized and unsynchronized access (which could be the case if each method call completes rapidly), the method includes a random delay: for threads whose Thread.ManagedThreadId property is even, the method calls Thread.Sleep to introduce a delay of 2,000 milliseconds. Weil die SyncResource-Klasse nicht öffentlich ist, löst keiner der Clientcodes eine Sperre für die synchronisierte Ressource aus, sondern die Sperre wird von der internen Klasse selbst ausgelöst.Note that, because the SyncResource class is not public, none of the client code takes a lock on the synchronized resource; the internal class itself takes the lock. Dadurch wird verhindert, dass bösartiger Code eine Sperre für ein öffentliches Objekt auslöst.This prevents malicious code from taking a lock on a public object.

using System;
using System.Threading;

internal class SyncResource
{
    // Use a monitor to enforce synchronization.
    public void Access()
    {
        lock(this) {
            Console.WriteLine("Starting synchronized resource access on thread #{0}",
                              Thread.CurrentThread.ManagedThreadId);
            if (Thread.CurrentThread.ManagedThreadId % 2 == 0)
                Thread.Sleep(2000);

            Thread.Sleep(200);
            Console.WriteLine("Stopping synchronized resource access on thread #{0}",
                              Thread.CurrentThread.ManagedThreadId);
        }
    }
}

internal class UnSyncResource
{
    // Do not enforce synchronization.
    public void Access()
    {
        Console.WriteLine("Starting unsynchronized resource access on Thread #{0}",
                          Thread.CurrentThread.ManagedThreadId);
        if (Thread.CurrentThread.ManagedThreadId % 2 == 0)
            Thread.Sleep(2000);

        Thread.Sleep(200);
        Console.WriteLine("Stopping unsynchronized resource access on thread #{0}",
                          Thread.CurrentThread.ManagedThreadId);
    }
}

public class App
{
    private static int numOps;
    private static AutoResetEvent opsAreDone = new AutoResetEvent(false);
    private static SyncResource SyncRes = new SyncResource();
    private static UnSyncResource UnSyncRes = new UnSyncResource();

   public static void Main()
   {
        // Set the number of synchronized calls.
        numOps = 5;
        for (int ctr = 0; ctr <= 4; ctr++)
            ThreadPool.QueueUserWorkItem(new WaitCallback(SyncUpdateResource));

        // Wait until this WaitHandle is signaled.
        opsAreDone.WaitOne();
        Console.WriteLine("\t\nAll synchronized operations have completed.\n");

        // Reset the count for unsynchronized calls.
        numOps = 5;
        for (int ctr = 0; ctr <= 4; ctr++)
            ThreadPool.QueueUserWorkItem(new WaitCallback(UnSyncUpdateResource));

        // Wait until this WaitHandle is signaled.
        opsAreDone.WaitOne();
        Console.WriteLine("\t\nAll unsynchronized thread operations have completed.\n");
   }

    static void SyncUpdateResource(Object state)
    {
        // Call the internal synchronized method.
        SyncRes.Access();

        // Ensure that only one thread can decrement the counter at a time.
        if (Interlocked.Decrement(ref numOps) == 0)
            // Announce to Main that in fact all thread calls are done.
            opsAreDone.Set();
    }

    static void UnSyncUpdateResource(Object state)
    {
        // Call the unsynchronized method.
        UnSyncRes.Access();

        // Ensure that only one thread can decrement the counter at a time.
        if (Interlocked.Decrement(ref numOps) == 0)
            // Announce to Main that in fact all thread calls are done.
            opsAreDone.Set();
    }
}
// The example displays output like the following:
//    Starting synchronized resource access on thread #6
//    Stopping synchronized resource access on thread #6
//    Starting synchronized resource access on thread #7
//    Stopping synchronized resource access on thread #7
//    Starting synchronized resource access on thread #3
//    Stopping synchronized resource access on thread #3
//    Starting synchronized resource access on thread #4
//    Stopping synchronized resource access on thread #4
//    Starting synchronized resource access on thread #5
//    Stopping synchronized resource access on thread #5
//
//    All synchronized operations have completed.
//
//    Starting unsynchronized resource access on Thread #7
//    Starting unsynchronized resource access on Thread #9
//    Starting unsynchronized resource access on Thread #10
//    Starting unsynchronized resource access on Thread #6
//    Starting unsynchronized resource access on Thread #3
//    Stopping unsynchronized resource access on thread #7
//    Stopping unsynchronized resource access on thread #9
//    Stopping unsynchronized resource access on thread #3
//    Stopping unsynchronized resource access on thread #10
//    Stopping unsynchronized resource access on thread #6
//
//    All unsynchronized thread operations have completed.
Imports System.Threading

Friend Class SyncResource
    ' Use a monitor to enforce synchronization.
    Public Sub Access()
        SyncLock Me
            Console.WriteLine("Starting synchronized resource access on thread #{0}",
                              Thread.CurrentThread.ManagedThreadId)
            If Thread.CurrentThread.ManagedThreadId Mod 2 = 0 Then
                Thread.Sleep(2000)
            End If
            Thread.Sleep(200)
            Console.WriteLine("Stopping synchronized resource access on thread #{0}",
                              Thread.CurrentThread.ManagedThreadId)
        End SyncLock
    End Sub
End Class

Friend Class UnSyncResource
    ' Do not enforce synchronization.
    Public Sub Access()
        Console.WriteLine("Starting unsynchronized resource access on Thread #{0}",
                          Thread.CurrentThread.ManagedThreadId)
        If Thread.CurrentThread.ManagedThreadId Mod 2 = 0 Then
            Thread.Sleep(2000)
        End If
        Thread.Sleep(200)
        Console.WriteLine("Stopping unsynchronized resource access on thread #{0}",
                          Thread.CurrentThread.ManagedThreadId)
    End Sub
End Class

Public Module App
    Private numOps As Integer
    Private opsAreDone As New AutoResetEvent(False)
    Private SyncRes As New SyncResource()
    Private UnSyncRes As New UnSyncResource()

    Public Sub Main()
        ' Set the number of synchronized calls.
        numOps = 5
        For ctr As Integer = 0 To 4
            ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf SyncUpdateResource))
        Next
        ' Wait until this WaitHandle is signaled.
        opsAreDone.WaitOne()
        Console.WriteLine(vbTab + vbNewLine + "All synchronized operations have completed.")
        Console.WriteLine()

        numOps = 5
        ' Reset the count for unsynchronized calls.
        For ctr As Integer = 0 To 4
            ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf UnSyncUpdateResource))
        Next

        ' Wait until this WaitHandle is signaled.
        opsAreDone.WaitOne()
        Console.WriteLine(vbTab + vbNewLine + "All unsynchronized thread operations have completed.")
    End Sub

    Sub SyncUpdateResource()
        ' Call the internal synchronized method.
        SyncRes.Access()

        ' Ensure that only one thread can decrement the counter at a time.
        If Interlocked.Decrement(numOps) = 0 Then
            ' Announce to Main that in fact all thread calls are done.
            opsAreDone.Set()
        End If
    End Sub

    Sub UnSyncUpdateResource()
        ' Call the unsynchronized method.
        UnSyncRes.Access()

        ' Ensure that only one thread can decrement the counter at a time.
        If Interlocked.Decrement(numOps) = 0 Then
            ' Announce to Main that in fact all thread calls are done.
            opsAreDone.Set()
        End If
    End Sub
End Module
' The example displays output like the following:
'    Starting synchronized resource access on thread #6
'    Stopping synchronized resource access on thread #6
'    Starting synchronized resource access on thread #7
'    Stopping synchronized resource access on thread #7
'    Starting synchronized resource access on thread #3
'    Stopping synchronized resource access on thread #3
'    Starting synchronized resource access on thread #4
'    Stopping synchronized resource access on thread #4
'    Starting synchronized resource access on thread #5
'    Stopping synchronized resource access on thread #5
'
'    All synchronized operations have completed.
'
'    Starting unsynchronized resource access on Thread #7
'    Starting unsynchronized resource access on Thread #9
'    Starting unsynchronized resource access on Thread #10
'    Starting unsynchronized resource access on Thread #6
'    Starting unsynchronized resource access on Thread #3
'    Stopping unsynchronized resource access on thread #7
'    Stopping unsynchronized resource access on thread #9
'    Stopping unsynchronized resource access on thread #3
'    Stopping unsynchronized resource access on thread #10
'    Stopping unsynchronized resource access on thread #6
'
'    All unsynchronized thread operations have completed.

Im Beispiel wird eine Variable, numOps, definiert, mit der die Anzahl von Threads festgelegt wird, die versuchen, auf die Ressource zuzugreifen.The example defines a variable, numOps, that defines the number of threads that will attempt to access the resource. Der Anwendungsthread ruft die ThreadPool.QueueUserWorkItem(WaitCallback)-Methode jeweils fünf Mal für synchronisierten und nicht synchronisierten Zugriff auf.The application thread calls the ThreadPool.QueueUserWorkItem(WaitCallback) method for synchronized and unsynchronized access five times each. Die ThreadPool.QueueUserWorkItem(WaitCallback)-Methode hat einen einzigen Parameter: ein Delegat, der keine Parameter akzeptiert und keinen Wert zurückgibt.The ThreadPool.QueueUserWorkItem(WaitCallback) method has a single parameter, a delegate that accepts no parameters and returns no value. Für synchronisierten Zugriff und ruft die Methode die SyncUpdateResourceMethode auf, für nicht synchronisierten Zugriff ruft sie die UnSyncUpdateResource-Methode auf.For synchronized access, it invokes the SyncUpdateResource method; for unsynchronized access, it invokes the UnSyncUpdateResource method. Nach jedem Satz von Methoden aufrufen ruft der Anwendungs Thread die AutoResetEvent. WaitOne -Methode auf, sodass er blockiert wird AutoResetEvent , bis die Instanz signalisiert wird.After each set of method calls, the application thread calls the AutoResetEvent.WaitOne method so that it blocks until the AutoResetEvent instance is signaled.

Bei jedem Aufruf der SyncUpdateResource-Methode wird die interne SyncResource.Access-Methode und dann die Interlocked.Decrement-Methode aufgerufen, um den numOps-Zähler zu dekrementieren.Each call to the SyncUpdateResource method calls the internal SyncResource.Access method and then calls the Interlocked.Decrement method to decrement the numOps counter. Die Interlocked.Decrement -Methode wird verwendet, um den Leistungswert zu verringern, da Sie andernfalls nicht sicher sein können, dass ein zweiter Thread auf den Wert zugreift, bevor der dekrementierte Wert des ersten Threads in der Variablen gespeichert wurde.The Interlocked.Decrement method Is used to decrement the counter, because otherwise you cannot be certain that a second thread will access the value before a first thread's decremented value has been stored in the variable. Wenn der letzte synchronisierte Arbeits Thread den Wert auf 0 (null) verringert und angibt, dass alle synchronisierten Threads den Zugriff SyncUpdateResource auf die Ressource EventWaitHandle.Set abgeschlossen haben, ruft die-Methode die-Methode auf, die den Fortschritt des Haupt Threads signalisiert. Niederlage.When the last synchronized worker thread decrements the counter to zero, indicating that all synchronized threads have completed accessing the resource, the SyncUpdateResource method calls the EventWaitHandle.Set method, which signals the main thread to continue execution.

Bei jedem Aufruf der UnSyncUpdateResource-Methode wird die interne UnSyncResource.Access-Methode und dann die Interlocked.Decrement-Methode aufgerufen, um den numOps-Zähler zu dekrementieren.Each call to the UnSyncUpdateResource method calls the internal UnSyncResource.Access method and then calls the Interlocked.Decrement method to decrement the numOps counter. Auch hier Interlocked.Decrement wird die-Methode verwendet, um den Leistungswert zu dekrementiert, um sicherzustellen, dass ein zweiter Thread nicht auf den Wert zugreift, bevor der Variablen der Wert eines ersten Threads zugewiesen wurde.Once again, the Interlocked.Decrement method Is used to decrement the counter to ensure that a second thread does not access the value before a first thread's decremented value has been assigned to the variable. Wenn der letzte nicht synchronisierte Arbeits Thread den Wert auf 0 (null) verringert, was darauf hinweist, dass keine nicht synchronisierten Threads auf UnSyncUpdateResource die Ressource zugreifen EventWaitHandle.Set müssen, ruft die Methode die-Methode auf, die den Haupt Thread signalisiert, die Ausführung fortzusetzen. .When the last unsynchronized worker thread decrements the counter to zero, indicating that no more unsynchronized threads need to access the resource, the UnSyncUpdateResource method calls the EventWaitHandle.Set method, which signals the main thread to continue execution.

Wie die Ausgabe des Beispiels zeigt, wird mit synchronisiertem Zugriff sichergestellt, dass der aufrufende Thread die geschützte Ressource beendet, bevor ein anderer Thread auf sie zugreifen kann. Jeder Thread wartet auf seinen Vorgänger.As the output from the example shows, synchronized access ensures that the calling thread exits the protected resource before another thread can access it; each thread waits on its predecessor. Andererseits, ohne die Sperre, wird die UnSyncResource.Access-Methode in der Reihenfolge aufgerufen, in der sie von Threads erreicht wird.On the other hand, without the lock, the UnSyncResource.Access method is called in the order in which threads reach it.

Hinweise

Mit Monitor der-Klasse können Sie den Zugriff auf einen Code Bereich synchronisieren, indem Sie eine Sperre für ein bestimmtes-Objekt durch Aufrufen Monitor.Enterder Monitor.TryEnterMethoden, Monitor.Exit und aufrufen.The Monitor class allows you to synchronize access to a region of code by taking and releasing a lock on a particular object by calling the Monitor.Enter, Monitor.TryEnter, and Monitor.Exit methods. Objekt Sperren bieten die Möglichkeit, den Zugriff auf einen Codeblock einzuschränken, der in der Regel als kritischer Abschnitt bezeichnet wird.Object locks provide the ability to restrict access to a block of code, commonly called a critical section. Während ein Thread die Sperre für ein Objekt besitzt, kann kein anderer Thread diese Sperre erwerben.While a thread owns the lock for an object, no other thread can acquire that lock. Sie können auch die Monitor -Klasse verwenden, um sicherzustellen, dass kein anderer Thread auf einen Abschnitt von Anwendungscode zugreifen darf, der vom Sperrenbesitzer ausgeführt wird, es sei denn, der andere Thread führt den Code mit einem anderen gesperrten Objekt aus.You can also use the Monitor class to ensure that no other thread is allowed to access a section of application code being executed by the lock owner, unless the other thread is executing the code using a different locked object.

In diesem Artikel:In this article:

Die Monitor-Klasse: Übersicht The Monitor class: An overview
Das Sperr Objekt The lock object
Kritischer Abschnitt The critical section
Pulse, pulall und Wait Pulse, PulseAll, and Wait
Monitore und Wait-HandlesMonitors and wait handles

Die Monitor-Klasse: ÜbersichtThe Monitor class: An overview

Monitorverfügt über die folgenden Features:Monitor has the following features:

  • Sie ist einem Objekt bei Bedarf zugeordnet.It is associated with an object on demand.

  • Die Bindung ist aufgehoben, d. h., Sie kann direkt aus jedem beliebigen Kontext aufgerufen werden.It is unbound, which means it can be called directly from any context.

  • Eine Instanz der Monitor -Klasse kann nicht erstellt werden. die Methoden Monitor der-Klasse sind alle statisch.An instance of the Monitor class cannot be created; the methods of the Monitor class are all static. Jeder Methode wird das synchronisierte Objekt, das den Zugriff auf den kritischen Abschnitt steuert, weitergegeben.Each method is passed the synchronized object that controls access to the critical section.

Hinweis

Verwenden Sie Monitor die-Klasse, um andere Objekte als Zeichen folgen (d. h. Stringandere Verweis Typen als) und keine Werttypen zu sperren.Use the Monitor class to lock objects other than strings (that is, reference types other than String), not value types. Weitere Informationen finden Sie in den über Ladungen der Enter -Methode und im Abschnitt Sperr Objekt weiter unten in diesem Artikel.For details, see the overloads of the Enter method and The lock object section later in this article.

In der folgenden Tabelle werden die Aktionen beschrieben, die von Threads durchgeführt werden können, die auf Synchronisierte Objekte zugreifen:The following table describes the actions that can be taken by threads that access synchronized objects:

AktionAction BeschreibungDescription
Enter, TryEnterEnter, TryEnter Ruft eine Sperre für ein Objekt ab.Acquires a lock for an object. Diese Aktion markiert auch den Anfang eines kritischen Abschnitts.This action also marks the beginning of a critical section. Es kann kein anderer Thread in den kritischen Abschnitt eintreten, es sei denn, er führt die Anweisungen im kritischen Abschnitt mithilfe eines anderen gesperrten Objekts aus.No other thread can enter the critical section unless it is executing the instructions in the critical section using a different locked object.
Wait Gibt die Sperre für ein Objekt frei, um anderen Threads das Sperren und Zugreifen auf das Objekt zu gestatten.Releases the lock on an object in order to permit other threads to lock and access the object. Der aufrufenden Thread wartet, während ein anderer Thread auf das Objekt zugreift.The calling thread waits while another thread accesses the object. Impuls Signale werden verwendet, um wartende Threads über Änderungen am Zustand eines Objekts zu benachrichtigen.Pulse signals are used to notify waiting threads about changes to an object's state.
Pulse (signal), PulseAllPulse (signal), PulseAll Sendet ein Signal an einen oder mehrere wartende Threads.Sends a signal to one or more waiting threads. Das Signal benachrichtigt einen wartenden Thread, dass sich der Zustand des gesperrten Objekts geändert hat, und der Besitzer der Sperre ist bereit, die Sperre freizugeben.The signal notifies a waiting thread that the state of the locked object has changed, and the owner of the lock is ready to release the lock. Der wartende Thread wird in die bereite Warteschlange des Objekts eingefügt, sodass er möglicherweise die Sperre für das Objekt erhält.The waiting thread is placed in the object's ready queue so that it might eventually receive the lock for the object. Sobald der Thread über die Sperre verfügt, kann er den neuen Status des Objekts überprüfen, um festzustellen, ob der erforderliche Zustand erreicht wurde.Once the thread has the lock, it can check the new state of the object to see if the required state has been reached.
Exit Gibt die Sperre für ein Objekt frei.Releases the lock on an object. Diese Aktion markiert auch das Ende eines kritischen Abschnitts, der durch das gesperrte-Objekt geschützt wird.This action also marks the end of a critical section protected by the locked object.

Ab gibt es zwei Sätze von über Ladungen für die-Methode und Enter die TryEnter -Methode. .NET Framework 4.NET Framework 4Beginning with the .NET Framework 4.NET Framework 4, there are two sets of overloads for the Enter and TryEnter methods. Ein Satz von über Ladungen verfügt über ref einen- C#Parameter ( ByRef in) oder einen Boolean -Parameter (in Visual Basic), true der atomisch auf festgelegt ist, wenn die Sperre abgerufen wird, selbst wenn eine Ausnahme ausgelöst wird, wenn die Sperre abgerufen wird.One set of overloads has a ref (in C#) or ByRef (in Visual Basic) Boolean parameter that is atomically set to true if the lock is acquired, even if an exception is thrown when acquiring the lock. Verwenden Sie diese über Ladungen, wenn es wichtig ist, die Sperre in allen Fällen aufzuheben, auch wenn sich die Ressourcen, die von der Sperre geschützt werden, möglicherweise nicht in einem konsistenten Zustand befinden.Use these overloads if it is critical to release the lock in all cases, even when the resources the lock is protecting might not be in a consistent state.

Das Sperr ObjektThe lock object

Die Monitor-Klasse besteht static aus den C#Methoden ( Shared in) oder (in Visual Basic), die auf ein Objekt angewendet werden, das den Zugriff auf den kritischen Abschnitt steuert.The Monitor class consists of static (in C#) or Shared (in Visual Basic) methods that operate on an object that controls access to the critical section. Die folgenden Informationen werden für jedes synchronisierte Objekt verwaltet:The following information is maintained for each synchronized object:

  • Ein Verweis auf den Thread, der die Sperre zurzeit enthält.A reference to the thread that currently holds the lock.

  • Ein Verweis auf eine bereite Warteschlange, die die Threads enthält, die zum Abrufen der Sperre bereit sind.A reference to a ready queue, which contains the threads that are ready to obtain the lock.

  • Ein Verweis auf eine Warteschlange, die die Threads enthält, die auf eine Änderung des Status des gesperrten Objekts warten.A reference to a waiting queue, which contains the threads that are waiting for notification of a change in the state of the locked object.

Monitor sperrt Objekte (d. h. Referenztypen), nicht Werttypen.Monitor locks objects (that is, reference types), not value types. Sie können einen Werttyp an Enter und Exit übergeben. Dieser wird jedoch für jeden Aufruf separat geschachtelt.While you can pass a value type to Enter and Exit, it is boxed separately for each call. Da jeder Aufruf ein separates Objekt erstellt, bedingt Enter nie eine Blockierung, und der Code, den die Methode eigentlich schützen soll, wird nicht wirklich synchronisiert.Since each call creates a separate object, Enter never blocks, and the code it is supposedly protecting is not really synchronized. Darüber hinaus unterscheiden sich das an Exit und das an Enter übergebene Objekt, sodass Monitor eine SynchronizationLockException mit der folgenden Meldung auslöst: "Die Objektsynchronisationsmethode wurde von einem nicht synchronisierten Codeblock aufgerufen."In addition, the object passed to Exit is different from the object passed to Enter, so Monitor throws SynchronizationLockException exception with the message "Object synchronization method was called from an unsynchronized block of code."

Dieses Problem wird anhand des folgenden Beispiels veranschaulicht.The following example illustrates this problem. Im Beispiel werden zehn Aufgaben gestartet, wobei jede lediglich 250 Millisekunden inaktiv ist.It launches ten tasks, each of which just sleeps for 250 milliseconds. Anschließend aktualisiert jede Aufgabe eine Zählervariable, nTasks, die dazu vorgesehen ist, die Anzahl von Aufgaben zu zählen, die tatsächlich gestartet wurden und ausgeführt werden.Each task then updates a counter variable, nTasks, which is intended to count the number of tasks that actually launched and executed. Weil nTasks eine globale Variable ist, die von mehreren Aufgaben gleichzeitig aktualisiert werden kann, wird ein Monitor verwendet, um zu verhindern, dass die Variable gleichzeitig von mehreren Aufgaben geändert wird.Because nTasks is a global variable that can be updated by multiple tasks simultaneously, a monitor is used to protect it from simultaneous modification by multiple tasks. Wie die Ausgabe des Beispiels zeigt, löst jede dieser Aufgaben jedoch eine SynchronizationLockException-Ausnahme aus.However, as the output from the example shows, each of the tasks throws a SynchronizationLockException exception.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {

      int nTasks = 0;
      List<Task> tasks = new List<Task>();
      
      try {
         for (int ctr = 0; ctr < 10; ctr++)
            tasks.Add(Task.Run( () => { // Instead of doing some work, just sleep.
                                        Thread.Sleep(250);
                                        // Increment the number of tasks.
                                        Monitor.Enter(nTasks);
                                        try {
                                           nTasks += 1;
                                        }
                                        finally {
                                           Monitor.Exit(nTasks);
                                        }
                                      } ));
         Task.WaitAll(tasks.ToArray());
         Console.WriteLine("{0} tasks started and executed.", nTasks);
      }
      catch (AggregateException e) {
         String msg = String.Empty;
         foreach (var ie in e.InnerExceptions) {
            Console.WriteLine("{0}", ie.GetType().Name);
            if (! msg.Contains(ie.Message))
               msg += ie.Message + Environment.NewLine;
         }
         Console.WriteLine("\nException Message(s):");
         Console.WriteLine(msg);
      }
   }
}
// The example displays the following output:
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//    SynchronizationLockException
//
//    Exception Message(s):
//    Object synchronization method was called from an unsynchronized block of code.
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim nTasks As Integer = 0
      Dim tasks As New List(Of Task)()

      Try
         For ctr As Integer = 0 To 9
            tasks.Add(Task.Run( Sub()
                                   ' Instead of doing some work, just sleep.
                                   Thread.Sleep(250)
                                   ' Increment the number of tasks.
                                   Monitor.Enter(nTasks)
                                   Try
                                      nTasks += 1
                                   Finally
                                      Monitor.Exit(nTasks)
                                   End Try
                                End Sub))
         Next
         Task.WaitAll(tasks.ToArray())
         Console.WriteLine("{0} tasks started and executed.", nTasks)
      Catch e As AggregateException
         Dim msg AS String = String.Empty
         For Each ie In e.InnerExceptions
            Console.WriteLine("{0}", ie.GetType().Name)
            If Not msg.Contains(ie.Message) Then
               msg += ie.Message + Environment.NewLine
            End If
         Next
         Console.WriteLine(vbCrLf + "Exception Message(s):")
         Console.WriteLine(msg)
      End Try
   End Sub
End Module
' The example displays the following output:
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'    SynchronizationLockException
'
'    Exception Message(s):
'    Object synchronization method was called from an unsynchronized block of code.

Jede Aufgabe löst eine SynchronizationLockException-Ausnahme aus, weil die Variable nTasks gekapselt wird, bevor in jeder Aufgabe die Monitor.Enter-Methode aufgerufen wird.Each task throws a SynchronizationLockException exception because the nTasks variable is boxed before the call to the Monitor.Enter method in each task. Anders formuliert heißt das, bei jedem Methodenaufruf wird eine separate Variable übergeben, die unabhängig von den anderen ist.In other words, each method call is passed a separate variable that is independent of the others. nTasks wird im Aufruf der Monitor.Exit-Methode erneut gekapselt.nTasks is boxed again in the call to the Monitor.Exit method. Dadurch werden wiederum zehn neue gekapselte nTasks-Variablen erstellt, die unabhängig voneinander sind. Hinzu kommen die zehn gekapselten Variablen, die im Aufruf der Monitor.Enter-Methode erstellt wurden.Once again, this creates ten new boxed variables, which are independent of each other, nTasks, and the ten boxed variables created in the call to the Monitor.Enter method. Die Ausnahme wird dann ausgelöst, weil im Code versucht wird, eine Sperre für eine neu erstellte Variable freizugeben, die zuvor nicht gesperrt wurde.The exception is thrown, then, because our code is attempting to release a lock on a newly created variable that was not previously locked.

Wie das folgende Beispiel zeigt, können Sie eine Werttypvariable zwar vor dem Aufruf von Enter und Exit kapseln und dasselbe gekapselte Objekt an beide Methoden übergeben, diese Vorgehensweise bietet jedoch keinerlei Vorteile.Although you can box a value type variable before calling Enter and Exit, as shown in the following example, and pass the same boxed object to both methods, there is no advantage to doing this. Änderungen an der nicht gekapselten Variablen wirken sich nicht auf die gekapselte Kopie aus, und es ist nicht möglich, den Wert der gekapselten Kopie zu ändern.Changes to the unboxed variable are not reflected in the boxed copy, and there is no way to change the value of the boxed copy.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {

      int nTasks = 0;
      object o = nTasks;
      List<Task> tasks = new List<Task>();
      
      try {
         for (int ctr = 0; ctr < 10; ctr++)
            tasks.Add(Task.Run( () => { // Instead of doing some work, just sleep.
                                        Thread.Sleep(250);
                                        // Increment the number of tasks.
                                        Monitor.Enter(o);
                                        try {
                                           nTasks++;
                                        }
                                        finally {
                                           Monitor.Exit(o);
                                        }
                                      } ));
         Task.WaitAll(tasks.ToArray());
         Console.WriteLine("{0} tasks started and executed.", nTasks);
      }
      catch (AggregateException e) {
         String msg = String.Empty;
         foreach (var ie in e.InnerExceptions) {
            Console.WriteLine("{0}", ie.GetType().Name);
            if (! msg.Contains(ie.Message))
               msg += ie.Message + Environment.NewLine;
         }
         Console.WriteLine("\nException Message(s):");
         Console.WriteLine(msg);
      }
   }
}
// The example displays the following output:
//        10 tasks started and executed.
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim nTasks As Integer = 0
      Dim o As Object = nTasks
      Dim tasks As New List(Of Task)()

      Try
         For ctr As Integer = 0 To 9
            tasks.Add(Task.Run( Sub()
                                   ' Instead of doing some work, just sleep.
                                   Thread.Sleep(250)
                                   ' Increment the number of tasks.
                                   Monitor.Enter(o)
                                   Try
                                      nTasks += 1
                                   Finally
                                      Monitor.Exit(o)
                                   End Try
                                End Sub))
         Next
         Task.WaitAll(tasks.ToArray())
         Console.WriteLine("{0} tasks started and executed.", nTasks)
      Catch e As AggregateException
         Dim msg AS String = String.Empty
         For Each ie In e.InnerExceptions
            Console.WriteLine("{0}", ie.GetType().Name)
            If Not msg.Contains(ie.Message) Then
               msg += ie.Message + Environment.NewLine
            End If
         Next
         Console.WriteLine(vbCrLf + "Exception Message(s):")
         Console.WriteLine(msg)
      End Try
   End Sub
End Module
' The example displays the following output:
'       10 tasks started and executed.

Wenn Sie ein Objekt auswählen, das synchronisiert werden soll, sollten Sie nur private oder interne Objekte sperren.When selecting an object on which to synchronize, you should lock only on private or internal objects. Sperren für externe Objekte können zu Deadlocks führen, da nicht verknüpften Code die gleichen Objekte auswählen kann, die für unterschiedliche Zwecke gesperrt werden sollen.Locking on external objects might result in deadlocks, because unrelated code could choose the same objects to lock on for different purposes.

Beachten Sie, dass Sie die Synchronisierung für ein Objekt in mehreren Anwendungs Domänen durchzuführen, wenn das MarshalByRefObjectfür die Sperre verwendete Objekt von abgeleitet ist.Note that you can synchronize on an object in multiple application domains if the object used for the lock derives from MarshalByRefObject.

Kritischer AbschnittThe critical section

Verwenden Sie Enter die Exit -Methode und die-Methode, um den Anfang und das Ende eines kritischen Abschnitts zu markieren.Use the Enter and Exit methods to mark the beginning and end of a critical section.

Hinweis

Enter Die von der-Methode und Exit der-Methode bereitgestellte Funktionalität ist mit der von der C# Lock-Anweisung in und der SyncLock -Anweisung in Visual Basic bereitgestellten Funktionalität identisch, außer dass die Sprachkonstrukte das Monitor.Enter(Object, Boolean)Methoden Überladung und Monitor.Exit die-Methode tryin einem...finallyThe functionality provided by the Enter and Exit methods is identical to that provided by the lock statement in C# and the SyncLock statement in Visual Basic, except that the language constructs wrap the Monitor.Enter(Object, Boolean) method overload and the Monitor.Exit method in a tryfinally blockieren, um sicherzustellen, dass der Monitor freigegeben wird.block to ensure that the monitor is released.

Wenn der kritische Abschnitt aus einer Reihe von zusammenhängenden Anweisungen besteht, gewährleistet die von der Enter -Methode abgerufene Sperre, dass nur ein einzelner Thread den eingeschlossenen Code mit dem gesperrten Objekt ausführen kann.If the critical section is a set of contiguous instructions, then the lock acquired by the Enter method guarantees that only a single thread can execute the enclosed code with the locked object. In diesem Fall wird empfohlen, dass Sie diesen Code in einem try -Block platzieren und den-Befehl in einem finally -Block an die Exit -Methode anordnen.In this case, we recommend that you place that code in a try block and place the call to the Exit method in a finally block. Dadurch ist sichergestellt, dass die Sperre aufgehoben wird, selbst wenn eine Ausnahme auftritt.This ensures that the lock is released even if an exception occurs. Dieses Muster wird im folgenden Code Fragment veranschaulicht.The following code fragment illustrates this pattern.

// Define the lock object.
var obj = new Object();

// Define the critical section.
Monitor.Enter(obj);
try {
   // Code to execute one thread at a time.
}
// catch blocks go here.
finally {
   Monitor.Exit(obj);
}
' Define the lock object.
Dim obj As New Object()

' Define the critical section.
Monitor.Enter(obj)
Try 
   ' Code to execute one thread at a time.

' catch blocks go here.
Finally 
   Monitor.Exit(obj)
End Try

Diese Funktion wird normalerweise verwendet, um den Zugriff auf eine statische Methode oder Instanzmethode einer Klasse zu synchronisieren.This facility is typically used to synchronize access to a static or instance method of a class.

Wenn ein kritischer Abschnitt eine gesamte Methode umfasst, kann die Sperre erreicht werden, indem das System.Runtime.CompilerServices.MethodImplAttribute -Objekt auf der-Methode platziert und der Synchronized Wert im Konstruktor von System.Runtime.CompilerServices.MethodImplAttributeangegeben wird.If a critical section spans an entire method, the locking facility can be achieved by placing the System.Runtime.CompilerServices.MethodImplAttribute on the method, and specifying the Synchronized value in the constructor of System.Runtime.CompilerServices.MethodImplAttribute. Wenn Sie dieses Attribut verwenden, werden Enter die Exit -und-Methodenaufrufe nicht benötigt.When you use this attribute, the Enter and Exit method calls are not needed. Dieses Muster wird im folgenden Code Fragment veranschaulicht:The following code fragment illustrates this pattern:

[MethodImplAttribute(MethodImplOptions.Synchronized)]
void MethodToLock()
{
   // Method implementation.
} 
<MethodImplAttribute(MethodImplOptions.Synchronized)>
Sub MethodToLock()
   ' Method implementation.
End Sub 

Beachten Sie, dass das-Attribut bewirkt, dass der aktuelle Thread die Sperre aufrecht hat, bis die Methode zurückgibt. Wenn die Sperre früher freigegeben werden kann, verwenden Monitor Sie die- C# Klasse, die Lock -Anweisung oder die Visual Basic SyncLock -Anweisung innerhalb der-Methode anstelle des-Attributs.Note that the attribute causes the current thread to hold the lock until the method returns; if the lock can be released sooner, use the Monitor class, the C# lock statement, or the Visual Basic SyncLock statement inside of the method instead of the attribute.

Es ist zwar möglich, dass Enter die Exit -und-Anweisungen, die ein angegebenes-Objekt Sperren und für übergreifende Member-oder Klassengrenzen oder beides freigeben, dies jedoch nicht empfehlenswert ist.While it is possible for the Enter and Exit statements that lock and release a given object to cross member or class boundaries or both, this practice is not recommended.

Pulse, pulall und WaitPulse, PulseAll, and Wait

Sobald ein Thread die Sperre besitzt und den kritischen Abschnitt eingegeben hat, den die Sperre schützt, kann er die Monitor.WaitMethoden Monitor.Pulse, und Monitor.PulseAll aufzurufen.Once a thread owns the lock and has entered the critical section that the lock protects, it can call the Monitor.Wait, Monitor.Pulse, and Monitor.PulseAll methods.

Wenn der Thread, der die Sperre enthält Wait, aufgerufen wird, wird die Sperre freigegeben, und der Thread wird der Warteschlange für das synchronisierte Objekt hinzugefügt.When the thread that holds the lock calls Wait, the lock is released and the thread is added to the waiting queue of the synchronized object. Der erste Thread in der Warteschlange, sofern vorhanden, erhält die Sperre und wechselt in den kritischen Abschnitt.The first thread in the ready queue, if any, acquires the lock and enters the critical section. Der Thread, der Wait aufgerufen hat, wird aus der Warteschlange in die Warteschlange verschoben Monitor.Pulse , wenn Monitor.PulseAll entweder die-Methode oder die-Methode von dem Thread aufgerufen wird, der die Sperre besitzt (der Thread muss sich an der Spitze der Warteschlange befinden).The thread that called Wait is moved from the waiting queue to the ready queue when either the Monitor.Pulse or the Monitor.PulseAll method is called by the thread that holds the lock (to be moved, the thread must be at the head of the waiting queue). Die Wait Methode gibt zurück, wenn der aufrufenden Thread die Sperre erneut erhält.The Wait method returns when the calling thread reacquires the lock.

Wenn der Thread, der die Sperre aufruft Pulse, aufruft, wird der Thread an der Spitze der Warteschlange in die bereite Warteschlange verschoben.When the thread that holds the lock calls Pulse, the thread at the head of the waiting queue is moved to the ready queue. Durch den- PulseAll Methodenaufrufe werden alle Threads aus der Warteschlange in die bereite Warteschlange verschoben.The call to the PulseAll method moves all the threads from the waiting queue to the ready queue.

Monitore und Wait-HandlesMonitors and wait handles

Es ist wichtig, den Unterschied zwischen der Verwendung Monitor der-Klasse und der- WaitHandle Objekte zu beachten.It is important to note the distinction between the use of the Monitor class and WaitHandle objects.

  • Die Monitor Klasse ist rein verwaltet, vollständig portabel und im Hinblick auf Betriebssystem-Ressourcenanforderungen effizienter.The Monitor class is purely managed, fully portable, and might be more efficient in terms of operating-system resource requirements.

  • WaitHandle-Objekte repräsentieren Objekte des Betriebssystems, die in der Lage sind, ihre Ausführung zu unterbrechen und zu warten. Sie sind für die Synchronisierung zwischen verwaltetem und nicht verwaltetem Code von Nutzen und machen einige höhere Betriebssystemfunktionen verfügbar, z. B. die Fähigkeit, auf viele Objekte gleichzeitig zu warten.WaitHandle objects represent operating-system waitable objects, are useful for synchronizing between managed and unmanaged code, and expose some advanced operating-system features like the ability to wait on many objects at once.

Eigenschaften

LockContentionCount

Ruft die Anzahl der Konflikte ab beim Versuch, die Sperre des Monitors aufzuheben.Gets the number of times there was contention when trying to take the monitor's lock.

Methoden

Enter(Object)

Erhält eine exklusive Sperre für das angegebene Objekt.Acquires an exclusive lock on the specified object.

Enter(Object, Boolean)

Erhält eine exklusive Sperre für das angegebene Objekt und legt atomar einen Wert fest, der angibt, ob die Sperre angenommen wurde.Acquires an exclusive lock on the specified object, and atomically sets a value that indicates whether the lock was taken.

Exit(Object)

Hebt eine exklusive Sperre für das angegebene Objekt auf.Releases an exclusive lock on the specified object.

IsEntered(Object)

Bestimmt, ob der aktuelle Thread die Sperre für das angegebene Objekt enthält.Determines whether the current thread holds the lock on the specified object.

Pulse(Object)

Benachrichtigt einen Thread in der Warteschlange für abzuarbeitende Threads über eine Änderung am Zustand des gesperrten Objekts.Notifies a thread in the waiting queue of a change in the locked object's state.

PulseAll(Object)

Benachrichtigt alle wartenden Threads über eine Änderung am Zustand des Objekts.Notifies all waiting threads of a change in the object's state.

TryEnter(Object)

Versucht, eine exklusive Sperre für das angegebene Objekt zu erhalten.Attempts to acquire an exclusive lock on the specified object.

TryEnter(Object, Boolean)

Versucht, eine exklusive Sperre für das angegebene Objekt zu erhalten, und legt atomar einen Wert fest, der angibt, ob die Sperre angenommen wurde.Attempts to acquire an exclusive lock on the specified object, and atomically sets a value that indicates whether the lock was taken.

TryEnter(Object, Int32)

Versucht über eine angegebene Anzahl von Millisekunden hinweg, eine exklusive Sperre für das angegebene Objekt zu erhalten.Attempts, for the specified number of milliseconds, to acquire an exclusive lock on the specified object.

TryEnter(Object, Int32, Boolean)

Versucht für die angegebene Anzahl von Millisekunden, eine exklusive Sperre für das angegebene Objekt zu erhalten, und legt atomar einen Wert fest, der angibt, ob die Sperre angenommen wurde.Attempts, for the specified number of milliseconds, to acquire an exclusive lock on the specified object, and atomically sets a value that indicates whether the lock was taken.

TryEnter(Object, TimeSpan)

Versucht über einen angegebenen Zeitraum hinweg, eine exklusive Sperre für das angegebene Objekt zu erhalten.Attempts, for the specified amount of time, to acquire an exclusive lock on the specified object.

TryEnter(Object, TimeSpan, Boolean)

Versucht für die angegebene Dauer, eine exklusive Sperre für das angegebene Objekt zu erhalten, und legt atomar einen Wert fest, der angibt, ob die Sperre angenommen wurde.Attempts, for the specified amount of time, to acquire an exclusive lock on the specified object, and atomically sets a value that indicates whether the lock was taken.

Wait(Object)

Hebt die Sperre für ein Objekt auf und blockiert den aktuellen Thread, bis er die Sperre erneut erhält.Releases the lock on an object and blocks the current thread until it reacquires the lock.

Wait(Object, Int32)

Hebt die Sperre für ein Objekt auf und blockiert den aktuellen Thread, bis er die Sperre erneut erhält.Releases the lock on an object and blocks the current thread until it reacquires the lock. Wenn das angegebene Timeoutintervall abläuft, tritt der Thread in die Warteschlange für abgearbeitete Threads ein.If the specified time-out interval elapses, the thread enters the ready queue.

Wait(Object, Int32, Boolean)

Hebt die Sperre für ein Objekt auf und blockiert den aktuellen Thread, bis er die Sperre erneut erhält.Releases the lock on an object and blocks the current thread until it reacquires the lock. Wenn das angegebene Timeoutintervall abläuft, tritt der Thread in die Warteschlange für abgearbeitete Threads ein.If the specified time-out interval elapses, the thread enters the ready queue. Diese Methode gibt außerdem an, ob die Synchronisierungsdomäne danach für den Kontext (wenn es sich um einen synchronisierten Kontext handelt) vor dem Warten und erneuten Erhalten verlassen wird.This method also specifies whether the synchronization domain for the context (if in a synchronized context) is exited before the wait and reacquired afterward.

Wait(Object, TimeSpan)

Hebt die Sperre für ein Objekt auf und blockiert den aktuellen Thread, bis er die Sperre erneut erhält.Releases the lock on an object and blocks the current thread until it reacquires the lock. Wenn das angegebene Timeoutintervall abläuft, tritt der Thread in die Warteschlange für abgearbeitete Threads ein.If the specified time-out interval elapses, the thread enters the ready queue.

Wait(Object, TimeSpan, Boolean)

Hebt die Sperre für ein Objekt auf und blockiert den aktuellen Thread, bis er die Sperre erneut erhält.Releases the lock on an object and blocks the current thread until it reacquires the lock. Wenn das angegebene Timeoutintervall abläuft, tritt der Thread in die Warteschlange für abgearbeitete Threads ein.If the specified time-out interval elapses, the thread enters the ready queue. Beendet vor dem Warten optional auch die Synchronisierungsdomäne für den synchronisierten Kontext und erhält die Domäne anschließend wieder.Optionally exits the synchronization domain for the synchronized context before the wait and reacquires the domain afterward.

Gilt für:

Threadsicherheit

Dieser Typ ist threadsicher.This type is thread safe.

Siehe auch