WaitHandle.WaitAny Méthode

Définition

Attend que l'un des éléments du tableau spécifié reçoive un signal.

Surcharges

WaitAny(WaitHandle[])

Attend que l'un des éléments du tableau spécifié reçoive un signal.

WaitAny(WaitHandle[], Int32)

Attend que l'un des éléments du tableau spécifié reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l'intervalle de temps.

WaitAny(WaitHandle[], TimeSpan)

Attend que l'un des éléments du tableau spécifié reçoive un signal, en utilisant une valeur TimeSpan pour spécifier l'intervalle de temps.

WaitAny(WaitHandle[], Int32, Boolean)

Attend que l’un des éléments du tableau spécifié reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l’intervalle de temps et en spécifiant s’il faut quitter le domaine de synchronisation avant l’attente.

WaitAny(WaitHandle[], TimeSpan, Boolean)

Attend que l’un des éléments du tableau spécifié reçoive un signal ; en utilisant une valeur TimeSpan pour spécifier l’intervalle de temps et en spécifiant s’il faut quitter le domaine de synchronisation avant l’attente.

WaitAny(WaitHandle[])

Attend que l'un des éléments du tableau spécifié reçoive un signal.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles);
static member WaitAny : System.Threading.WaitHandle[] -> int
Public Shared Function WaitAny (waitHandles As WaitHandle()) As Integer

Paramètres

waitHandles
WaitHandle[]

Tableau WaitHandle qui contient les objets que l'instance actuelle attendra.

Retours

Index du tableau de l'objet ayant respecté l'attente.

Exceptions

Le paramètre waitHandles a la valeur null.

- ou -

Un ou plusieurs des objets dans le tableau waitHandles sont null.

Le nombre d’objets dans waitHandles est supérieur à ce que le système autorise.

waitHandles est un tableau qui ne contient aucun élément et la version du .NET Framework est 1.0 ou 1.1.

L’attente s’est arrêtée, car un thread s’est terminé sans libérer de mutex.

waitHandles est un tableau qui ne contient aucun élément et la version du .NET Framework est 2.0 ou ultérieure.

Le tableau waitHandles contient un proxy transparent pour un WaitHandle dans un autre domaine d’application.

Exemples

L’exemple de code suivant illustre l’appel de la WaitAny méthode .

using namespace System;
using namespace System::Threading;

public ref class WaitHandleExample
{
    // Define a random number generator for testing.
private:
    static Random^ random = gcnew Random();
public:
    static void DoTask(Object^ state)
    {
        AutoResetEvent^ autoReset = (AutoResetEvent^) state;
        int time = 1000 * random->Next(2, 10);
        Console::WriteLine("Performing a task for {0} milliseconds.", time);
        Thread::Sleep(time);
        autoReset->Set();
    }
};

int main()
{
    // Define an array with two AutoResetEvent WaitHandles.
    array<WaitHandle^>^ handles = gcnew array<WaitHandle^> {
        gcnew AutoResetEvent(false), gcnew AutoResetEvent(false)};

    // Queue up two tasks on two different threads;
    // wait until all tasks are completed.
    DateTime timeInstance = DateTime::Now;
    Console::WriteLine("Main thread is waiting for BOTH tasks to " +
        "complete.");
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[0]);
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[1]);
    WaitHandle::WaitAll(handles);
    // The time shown below should match the longest task.
    Console::WriteLine("Both tasks are completed (time waited={0})",
        (DateTime::Now - timeInstance).TotalMilliseconds);

    // Queue up two tasks on two different threads;
    // wait until any tasks are completed.
    timeInstance = DateTime::Now;
    Console::WriteLine();
    Console::WriteLine("The main thread is waiting for either task to " +
        "complete.");
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[0]);
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[1]);
    int index = WaitHandle::WaitAny(handles);
    // The time shown below should match the shortest task.
    Console::WriteLine("Task {0} finished first (time waited={1}).",
        index + 1, (DateTime::Now - timeInstance).TotalMilliseconds);
}

// This code produces the following sample output.
//
// Main thread is waiting for BOTH tasks to complete.
// Performing a task for 7000 milliseconds.
// Performing a task for 4000 milliseconds.
// Both tasks are completed (time waited=7064.8052)

// The main thread is waiting for either task to complete.
// Performing a task for 2000 milliseconds.
// Performing a task for 2000 milliseconds.
// Task 1 finished first (time waited=2000.6528).
using System;
using System.Threading;

public sealed class App
{
    // Define an array with two AutoResetEvent WaitHandles.
    static WaitHandle[] waitHandles = new WaitHandle[]
    {
        new AutoResetEvent(false),
        new AutoResetEvent(false)
    };

    // Define a random number generator for testing.
    static Random r = new Random();

    static void Main()
    {
        // Queue up two tasks on two different threads;
        // wait until all tasks are completed.
        DateTime dt = DateTime.Now;
        Console.WriteLine("Main thread is waiting for BOTH tasks to complete.");
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
        WaitHandle.WaitAll(waitHandles);
        // The time shown below should match the longest task.
        Console.WriteLine("Both tasks are completed (time waited={0})",
            (DateTime.Now - dt).TotalMilliseconds);

        // Queue up two tasks on two different threads;
        // wait until any task is completed.
        dt = DateTime.Now;
        Console.WriteLine();
        Console.WriteLine("The main thread is waiting for either task to complete.");
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
        int index = WaitHandle.WaitAny(waitHandles);
        // The time shown below should match the shortest task.
        Console.WriteLine("Task {0} finished first (time waited={1}).",
            index + 1, (DateTime.Now - dt).TotalMilliseconds);
    }

    static void DoTask(Object state)
    {
        AutoResetEvent are = (AutoResetEvent) state;
        int time = 1000 * r.Next(2, 10);
        Console.WriteLine("Performing a task for {0} milliseconds.", time);
        Thread.Sleep(time);
        are.Set();
    }
}

// This code produces output similar to the following:
//
//  Main thread is waiting for BOTH tasks to complete.
//  Performing a task for 7000 milliseconds.
//  Performing a task for 4000 milliseconds.
//  Both tasks are completed (time waited=7064.8052)
//
//  The main thread is waiting for either task to complete.
//  Performing a task for 2000 milliseconds.
//  Performing a task for 2000 milliseconds.
//  Task 1 finished first (time waited=2000.6528).
Imports System.Threading

NotInheritable Public Class App
    ' Define an array with two AutoResetEvent WaitHandles.
    Private Shared waitHandles() As WaitHandle = _
        {New AutoResetEvent(False), New AutoResetEvent(False)}
    
    ' Define a random number generator for testing.
    Private Shared r As New Random()
    
    <MTAThreadAttribute> _
    Public Shared Sub Main() 
        ' Queue two tasks on two different threads; 
        ' wait until all tasks are completed.
        Dim dt As DateTime = DateTime.Now
        Console.WriteLine("Main thread is waiting for BOTH tasks to complete.")
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0))
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1))
        WaitHandle.WaitAll(waitHandles)
        ' The time shown below should match the longest task.
        Console.WriteLine("Both tasks are completed (time waited={0})", _
            (DateTime.Now - dt).TotalMilliseconds)
        
        ' Queue up two tasks on two different threads; 
        ' wait until any tasks are completed.
        dt = DateTime.Now
        Console.WriteLine()
        Console.WriteLine("The main thread is waiting for either task to complete.")
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0))
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1))
        Dim index As Integer = WaitHandle.WaitAny(waitHandles)
        ' The time shown below should match the shortest task.
        Console.WriteLine("Task {0} finished first (time waited={1}).", _
            index + 1,(DateTime.Now - dt).TotalMilliseconds)
    
    End Sub
    
    Shared Sub DoTask(ByVal state As [Object]) 
        Dim are As AutoResetEvent = CType(state, AutoResetEvent)
        Dim time As Integer = 1000 * r.Next(2, 10)
        Console.WriteLine("Performing a task for {0} milliseconds.", time)
        Thread.Sleep(time)
        are.Set()
    
    End Sub
End Class

' This code produces output similar to the following:
'
'  Main thread is waiting for BOTH tasks to complete.
'  Performing a task for 7000 milliseconds.
'  Performing a task for 4000 milliseconds.
'  Both tasks are completed (time waited=7064.8052)
' 
'  The main thread is waiting for either task to complete.
'  Performing a task for 2000 milliseconds.
'  Performing a task for 2000 milliseconds.
'  Task 1 finished first (time waited=2000.6528).

Remarques

AbandonedMutexException est nouveau dans .NET Framework version 2.0. Dans les versions précédentes, la WaitAny méthode retourne true si l’attente se termine, car un mutex est abandonné. Un mutex abandonné indique souvent une erreur de codage grave. Dans le cas d’un mutex à l’échelle du système, cela peut indiquer qu’une application a été arrêtée brusquement (par exemple, à l’aide du Gestionnaire des tâches Windows). L’exception contient des informations utiles pour le débogage.

La WaitAny méthode lève un AbandonedMutexException uniquement lorsque l’attente se termine en raison d’un mutex abandonné. Si waitHandles contient un mutex libéré avec un numéro d’index inférieur à celui du mutex abandonné, la WaitAny méthode se termine normalement et l’exception n’est pas levée.

Notes

Dans les versions du .NET Framework antérieures à la version 2.0, si un thread quitte ou abandonne sans publier explicitement un Mutex, et qu’il Mutex se trouve à l’index 0 (zéro) dans un tableau sur un WaitAny autre thread, l’index retourné par WaitAny est 128 au lieu de 0.

Cette méthode retourne quand un handle est signalé. Si plusieurs objets sont signalés pendant l’appel, la valeur de retour est l’index de tableau de l’objet signalé avec la plus petite valeur d’index de tous les objets signalés.

Le nombre maximal de handles d’attente est 64 et 63 si le thread actuel est à STA l’état.

L’appel de cette surcharge de méthode équivaut à appeler la WaitAny(WaitHandle[], Int32, Boolean) surcharge de méthode et à spécifier -1 (ou Timeout.Infinite) pour millisecondsTimeout et true pour exitContext.

S’applique à

WaitAny(WaitHandle[], Int32)

Attend que l'un des éléments du tableau spécifié reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l'intervalle de temps.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout);
static member WaitAny : System.Threading.WaitHandle[] * int -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), millisecondsTimeout As Integer) As Integer

Paramètres

waitHandles
WaitHandle[]

Tableau WaitHandle qui contient les objets que l'instance actuelle attendra.

millisecondsTimeout
Int32

Nombre de millisecondes à attendre, ou Infinite (-1) pour un délai d'attente infini.

Retours

Index de tableau de l'objet ayant respecté l'attente ou WaitTimeout si aucun objet n'a respecté l'attente et qu'un intervalle de temps équivalent à millisecondsTimeout s'est écoulé.

Exceptions

Le paramètre waitHandles a la valeur null.

- ou -

Un ou plusieurs des objets dans le tableau waitHandles sont null.

Le nombre d’objets dans waitHandles est supérieur à ce que le système autorise.

millisecondsTimeout est un nombre négatif différent de -1, qui représente un délai d’attente infini.

L’attente s’est arrêtée, car un thread s’est terminé sans libérer de mutex.

waitHandles est un tableau sans éléments.

Le tableau waitHandles contient un proxy transparent pour un WaitHandle dans un autre domaine d’application.

Remarques

Si millisecondsTimeout est zéro, la méthode ne bloque pas. Il teste l’état des handles d’attente et retourne immédiatement.

La WaitAny méthode lève un AbandonedMutexException uniquement lorsque l’attente se termine en raison d’un mutex abandonné. Si waitHandles contient un mutex libéré avec un numéro d’index inférieur à celui du mutex abandonné, la WaitAny méthode se termine normalement et l’exception n’est pas levée.

Cette méthode retourne lorsque l’attente se termine, soit lorsque l’un des handles est signalé, soit lorsqu’un délai d’attente se produit. Si plusieurs objets sont signalés pendant l’appel, la valeur de retour est l’index de tableau de l’objet signalé avec la plus petite valeur d’index de tous les objets signalés.

Le nombre maximal de handles d’attente est 64 et 63 si le thread actuel est à STA l’état.

L’appel de cette surcharge de méthode revient à appeler la WaitAny(WaitHandle[], Int32, Boolean) surcharge et à false spécifier pour exitContext.

S’applique à

WaitAny(WaitHandle[], TimeSpan)

Attend que l'un des éléments du tableau spécifié reçoive un signal, en utilisant une valeur TimeSpan pour spécifier l'intervalle de temps.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, TimeSpan timeout);
static member WaitAny : System.Threading.WaitHandle[] * TimeSpan -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), timeout As TimeSpan) As Integer

Paramètres

waitHandles
WaitHandle[]

Tableau WaitHandle qui contient les objets que l'instance actuelle attendra.

timeout
TimeSpan

TimeSpan qui représente le nombre de millièmes de secondes à attendre ou TimeSpan qui représente -1 millième de seconde, pour attendre indéfiniment.

Retours

Index de tableau de l'objet ayant respecté l'attente ou WaitTimeout si aucun objet n'a respecté l'attente et qu'un intervalle de temps équivalent à timeout s'est écoulé.

Exceptions

Le paramètre waitHandles a la valeur null.

- ou -

Un ou plusieurs des objets dans le tableau waitHandles sont null.

Le nombre d’objets dans waitHandles est supérieur à ce que le système autorise.

timeout est un nombre négatif différent de -1 milliseconde, qui représente un délai d’attente infini.

-ou-

timeout est supérieur à Int32.MaxValue.

L’attente s’est arrêtée, car un thread s’est terminé sans libérer de mutex.

waitHandles est un tableau sans éléments.

Le tableau waitHandles contient un proxy transparent pour un WaitHandle dans un autre domaine d’application.

Remarques

Si timeout est zéro, la méthode ne bloque pas. Il teste l’état des handles d’attente et retourne immédiatement.

La WaitAny méthode lève un AbandonedMutexException uniquement lorsque l’attente se termine en raison d’un mutex abandonné. Si waitHandles contient un mutex libéré avec un numéro d’index inférieur à celui du mutex abandonné, la WaitAny méthode se termine normalement et l’exception n’est pas levée.

Cette méthode retourne lorsque l’attente se termine, soit lorsque l’un des handles est signalé, soit lorsqu’un délai d’attente se produit. Si plusieurs objets sont signalés pendant l’appel, la valeur de retour est l’index de tableau de l’objet signalé avec la plus petite valeur d’index de tous les objets signalés.

Le nombre maximal de handles d’attente est 64 et 63 si le thread actuel est à STA l’état.

La valeur maximale pour timeout est Int32.MaxValue.

L’appel de cette surcharge de méthode revient à appeler la WaitAny(WaitHandle[], TimeSpan, Boolean) surcharge et à false spécifier pour exitContext.

S’applique à

WaitAny(WaitHandle[], Int32, Boolean)

Attend que l’un des éléments du tableau spécifié reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l’intervalle de temps et en spécifiant s’il faut quitter le domaine de synchronisation avant l’attente.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout, bool exitContext);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext);
static member WaitAny : System.Threading.WaitHandle[] * int * bool -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), millisecondsTimeout As Integer, exitContext As Boolean) As Integer

Paramètres

waitHandles
WaitHandle[]

Tableau WaitHandle qui contient les objets que l'instance actuelle attendra.

millisecondsTimeout
Int32

Nombre de millisecondes à attendre, ou Infinite (-1) pour un délai d'attente infini.

exitContext
Boolean

true pour quitter le domaine de synchronisation du contexte avant l'attente (dans le cas d'un contexte synchronisé) et l'acquérir à nouveau ensuite ; sinon, false.

Retours

Index de tableau de l'objet ayant respecté l'attente ou WaitTimeout si aucun objet n'a respecté l'attente et qu'un intervalle de temps équivalent à millisecondsTimeout s'est écoulé.

Exceptions

Le paramètre waitHandles a la valeur null.

- ou -

Un ou plusieurs des objets dans le tableau waitHandles sont null.

Le nombre d’objets dans waitHandles est supérieur à ce que le système autorise.

waitHandles est un tableau qui ne contient aucun élément et la version du .NET Framework est 1.0 ou 1.1.

millisecondsTimeout est un nombre négatif différent de -1, qui représente un délai d’attente infini.

L’attente s’est arrêtée, car un thread s’est terminé sans libérer de mutex.

waitHandles est un tableau qui ne contient aucun élément et la version du .NET Framework est 2.0 ou ultérieure.

Le tableau waitHandles contient un proxy transparent pour un WaitHandle dans un autre domaine d’application.

Exemples

L’exemple de code suivant montre comment utiliser le pool de threads pour rechercher simultanément un fichier sur plusieurs disques. Pour les considérations relatives à l’espace, seul le répertoire racine de chaque disque fait l’objet d’une recherche.

using namespace System;
using namespace System::IO;
using namespace System::Threading;
ref class Search
{
private:

   // Maintain state information to pass to FindCallback.
   ref class State
   {
   public:
      AutoResetEvent^ autoEvent;
      String^ fileName;
      State( AutoResetEvent^ autoEvent, String^ fileName )
         : autoEvent( autoEvent ), fileName( fileName )
      {}

   };


public:
   array<AutoResetEvent^>^autoEvents;
   array<String^>^diskLetters;

   // Search for stateInfo->fileName.
   void FindCallback( Object^ state )
   {
      State^ stateInfo = dynamic_cast<State^>(state);
      
      // Signal if the file is found.
      if ( File::Exists( stateInfo->fileName ) )
      {
         stateInfo->autoEvent->Set();
      }
   }

   Search()
   {
      
      // Retrieve an array of disk letters.
      diskLetters = Environment::GetLogicalDrives();
      autoEvents = gcnew array<AutoResetEvent^>(diskLetters->Length);
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         autoEvents[ i ] = gcnew AutoResetEvent( false );

      }
   }


   // Search for fileName in the root directory of all disks.
   void FindFile( String^ fileName )
   {
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         Console::WriteLine(  "Searching for {0} on {1}.", fileName, diskLetters[ i ] );
         ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Search::FindCallback ), gcnew State( autoEvents[ i ],String::Concat( diskLetters[ i ], fileName ) ) );

      }
      
      // Wait for the first instance of the file to be found.
      int index = WaitHandle::WaitAny( autoEvents, 3000, false );
      if ( index == WaitHandle::WaitTimeout )
      {
         Console::WriteLine( "\n{0} not found.", fileName );
      }
      else
      {
         Console::WriteLine( "\n{0} found on {1}.", fileName, diskLetters[ index ] );
      }
   }

};

int main()
{
   Search^ search = gcnew Search;
   search->FindFile( "SomeFile.dat" );
}
using System;
using System.IO;
using System.Threading;

class Test
{
    static void Main()
    {
        Search search = new Search();
        search.FindFile("SomeFile.dat");
    }
}

class Search
{
    // Maintain state information to pass to FindCallback.
    class State
    {
        public AutoResetEvent autoEvent;
        public string         fileName;

        public State(AutoResetEvent autoEvent, string fileName)
        {
            this.autoEvent    = autoEvent;
            this.fileName     = fileName;
        }
    }

    AutoResetEvent[] autoEvents;
    String[] diskLetters;

    public Search()
    {
        // Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives();

        autoEvents = new AutoResetEvent[diskLetters.Length];
        for(int i = 0; i < diskLetters.Length; i++)
        {
            autoEvents[i] = new AutoResetEvent(false);
        }
    }

    // Search for fileName in the root directory of all disks.
    public void FindFile(string fileName)
    {
        for(int i = 0; i < diskLetters.Length; i++)
        {
            Console.WriteLine("Searching for {0} on {1}.",
                fileName, diskLetters[i]);
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(FindCallback), 
                new State(autoEvents[i], diskLetters[i] + fileName));
        }

        // Wait for the first instance of the file to be found.
        int index = WaitHandle.WaitAny(autoEvents, 3000, false);
        if(index == WaitHandle.WaitTimeout)
        {
            Console.WriteLine("\n{0} not found.", fileName);
        }
        else
        {
            Console.WriteLine("\n{0} found on {1}.", fileName,
                diskLetters[index]);
        }
    }

    // Search for stateInfo.fileName.
    void FindCallback(object state)
    {
        State stateInfo = (State)state;

        // Signal if the file is found.
        if(File.Exists(stateInfo.fileName))
        {
            stateInfo.autoEvent.Set();
        }
    }
}
Imports System.IO
Imports System.Threading

Public Class Test

    <MTAThread> _
    Shared Sub Main()
        Dim search As New Search()
        search.FindFile("SomeFile.dat")
    End Sub    
End Class

Public Class Search

    ' Maintain state information to pass to FindCallback.
    Class State
        Public autoEvent As AutoResetEvent 
        Public fileName As String         

        Sub New(anEvent As AutoResetEvent, fName As String)
            autoEvent = anEvent
            fileName = fName
        End Sub
    End Class

    Dim autoEvents() As AutoResetEvent
    Dim diskLetters() As String

    Sub New()

        ' Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives()

        autoEvents = New AutoResetEvent(diskLetters.Length - 1) {}
        For i As Integer = 0 To diskLetters.Length - 1
            autoEvents(i) = New AutoResetEvent(False)
        Next i
    End Sub    
    
    ' Search for fileName in the root directory of all disks.
    Sub FindFile(fileName As String)
        For i As Integer = 0 To diskLetters.Length - 1
            Console.WriteLine("Searching for {0} on {1}.", _
                fileName, diskLetters(i))
        
            ThreadPool.QueueUserWorkItem(AddressOf FindCallback, _ 
                New State(autoEvents(i), diskLetters(i) & fileName))
        Next i

        ' Wait for the first instance of the file to be found.
        Dim index As Integer = _
            WaitHandle.WaitAny(autoEvents, 3000, False)
        If index = WaitHandle.WaitTimeout
            Console.WriteLine(vbCrLf & "{0} not found.", fileName)
        Else
            Console.WriteLine(vbCrLf & "{0} found on {1}.", _
                fileName, diskLetters(index))
        End If
    End Sub

    ' Search for stateInfo.fileName.
    Sub FindCallback(state As Object)
        Dim stateInfo As State = DirectCast(state, State)

        ' Signal if the file is found.
        If File.Exists(stateInfo.fileName) Then
            stateInfo.autoEvent.Set()
        End If
    End Sub

End Class

Remarques

Si millisecondsTimeout est zéro, la méthode ne bloque pas. Il teste l’état des handles d’attente et retourne immédiatement.

La WaitAny méthode lève un AbandonedMutexException uniquement lorsque l’attente se termine en raison d’un mutex abandonné. Si waitHandles contient un mutex libéré avec un numéro d’index inférieur à celui du mutex abandonné, la WaitAny méthode se termine normalement et l’exception n’est pas levée. Un mutex abandonné indique souvent une erreur de codage grave. Dans le cas d’un mutex à l’échelle du système, cela peut indiquer qu’une application a été arrêtée brusquement (par exemple, à l’aide du Gestionnaire des tâches Windows). L’exception contient des informations utiles pour le débogage.

Cette méthode retourne lorsque l’attente se termine, soit lorsque l’un des handles est signalé, soit lorsqu’un délai d’attente se produit. Si plusieurs objets sont signalés pendant l’appel, la valeur de retour est l’index de tableau de l’objet signalé avec la plus petite valeur d’index de tous les objets signalés.

Le nombre maximal de handles d’attente est 64 et 63 si le thread actuel est à STA l’état.

Sortie du contexte

Le exitContext paramètre n’a aucun effet, sauf si cette méthode est appelée à partir d’un contexte managé non par défaut. Le contexte managé peut être non défini par défaut si votre thread se trouve à l’intérieur d’un appel à un instance d’une classe dérivée de ContextBoundObject. Même si vous exécutez actuellement une méthode sur une classe qui n’est pas dérivée de ContextBoundObject, comme String, vous pouvez être dans un contexte non par défaut si un ContextBoundObject se trouve sur votre pile dans le domaine d’application actuel.

Lorsque votre code s’exécute dans un contexte non par défaut, la spécification true pour exitContext entraîne la sortie du thread du contexte managé non par défaut (autrement dit, pour passer au contexte par défaut) avant d’exécuter cette méthode. Le thread retourne au contexte non par défaut d’origine une fois l’appel à cette méthode terminé.

La sortie du contexte peut être utile lorsque la classe liée au contexte a l’attribut SynchronizationAttribute . Dans ce cas, tous les appels aux membres de la classe sont automatiquement synchronisés et le domaine de synchronisation est l’ensemble du corps du code de la classe. Si le code dans la pile d’appels d’un membre appelle cette méthode et spécifie true pour exitContext, le thread quitte le domaine de synchronisation, ce qui permet à un thread bloqué sur un appel à n’importe quel membre de l’objet de continuer. Lorsque cette méthode est retournée, le thread qui a effectué l’appel doit attendre d’être réentrée dans le domaine de synchronisation.

S’applique à

WaitAny(WaitHandle[], TimeSpan, Boolean)

Attend que l’un des éléments du tableau spécifié reçoive un signal ; en utilisant une valeur TimeSpan pour spécifier l’intervalle de temps et en spécifiant s’il faut quitter le domaine de synchronisation avant l’attente.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout, bool exitContext);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext);
static member WaitAny : System.Threading.WaitHandle[] * TimeSpan * bool -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), timeout As TimeSpan, exitContext As Boolean) As Integer

Paramètres

waitHandles
WaitHandle[]

Tableau WaitHandle qui contient les objets que l'instance actuelle attendra.

timeout
TimeSpan

TimeSpan qui représente le nombre de millièmes de secondes à attendre ou TimeSpan qui représente -1 millième de seconde, pour attendre indéfiniment.

exitContext
Boolean

true pour quitter le domaine de synchronisation du contexte avant l'attente (dans le cas d'un contexte synchronisé) et l'acquérir à nouveau ensuite ; sinon, false.

Retours

Index de tableau de l'objet ayant respecté l'attente ou WaitTimeout si aucun objet n'a respecté l'attente et qu'un intervalle de temps équivalent à timeout s'est écoulé.

Exceptions

Le paramètre waitHandles a la valeur null.

- ou -

Un ou plusieurs des objets dans le tableau waitHandles sont null.

Le nombre d’objets dans waitHandles est supérieur à ce que le système autorise.

waitHandles est un tableau qui ne contient aucun élément et la version du .NET Framework est 1.0 ou 1.1.

timeout est un nombre négatif différent de -1 milliseconde, qui représente un délai d’attente infini.

-ou-

timeout est supérieur à Int32.MaxValue.

L’attente s’est arrêtée, car un thread s’est terminé sans libérer de mutex.

waitHandles est un tableau qui ne contient aucun élément et la version du .NET Framework est 2.0 ou ultérieure.

Le tableau waitHandles contient un proxy transparent pour un WaitHandle dans un autre domaine d’application.

Exemples

L’exemple de code suivant montre comment utiliser le pool de threads pour rechercher simultanément un fichier sur plusieurs disques. Pour les considérations relatives à l’espace, seul le répertoire racine de chaque disque fait l’objet d’une recherche.

using namespace System;
using namespace System::IO;
using namespace System::Threading;
ref class Search
{
private:

   // Maintain state information to pass to FindCallback.
   ref class State
   {
   public:
      AutoResetEvent^ autoEvent;
      String^ fileName;
      State( AutoResetEvent^ autoEvent, String^ fileName )
         : autoEvent( autoEvent ), fileName( fileName )
      {}

   };


public:
   array<AutoResetEvent^>^autoEvents;
   array<String^>^diskLetters;

   // Search for stateInfo->fileName.
   void FindCallback( Object^ state )
   {
      State^ stateInfo = dynamic_cast<State^>(state);
      
      // Signal if the file is found.
      if ( File::Exists( stateInfo->fileName ) )
      {
         stateInfo->autoEvent->Set();
      }
   }

   Search()
   {
      
      // Retrieve an array of disk letters.
      diskLetters = Environment::GetLogicalDrives();
      autoEvents = gcnew array<AutoResetEvent^>(diskLetters->Length);
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         autoEvents[ i ] = gcnew AutoResetEvent( false );

      }
   }


   // Search for fileName in the root directory of all disks.
   void FindFile( String^ fileName )
   {
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         Console::WriteLine(  "Searching for {0} on {1}.", fileName, diskLetters[ i ] );
         ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Search::FindCallback ), gcnew State( autoEvents[ i ],String::Concat( diskLetters[ i ], fileName ) ) );

      }
      
      // Wait for the first instance of the file to be found.
      int index = WaitHandle::WaitAny( autoEvents, TimeSpan(0,0,3), false );
      if ( index == WaitHandle::WaitTimeout )
      {
         Console::WriteLine( "\n{0} not found.", fileName );
      }
      else
      {
         Console::WriteLine( "\n{0} found on {1}.", fileName, diskLetters[ index ] );
      }
   }

};

int main()
{
   Search^ search = gcnew Search;
   search->FindFile( "SomeFile.dat" );
}
using System;
using System.IO;
using System.Threading;

class Test
{
    static void Main()
    {
        Search search = new Search();
        search.FindFile("SomeFile.dat");
    }
}

class Search
{
    // Maintain state information to pass to FindCallback.
    class State
    {
        public AutoResetEvent autoEvent;
        public string         fileName;

        public State(AutoResetEvent autoEvent, string fileName)
        {
            this.autoEvent    = autoEvent;
            this.fileName     = fileName;
        }
    }

    AutoResetEvent[] autoEvents;
    String[] diskLetters;

    public Search()
    {
        // Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives();

        autoEvents = new AutoResetEvent[diskLetters.Length];
        for(int i = 0; i < diskLetters.Length; i++)
        {
            autoEvents[i] = new AutoResetEvent(false);
        }
    }

    // Search for fileName in the root directory of all disks.
    public void FindFile(string fileName)
    {
        for(int i = 0; i < diskLetters.Length; i++)
        {
            Console.WriteLine("Searching for {0} on {1}.",
                fileName, diskLetters[i]);
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(FindCallback), 
                new State(autoEvents[i], diskLetters[i] + fileName));
        }

        // Wait for the first instance of the file to be found.
        int index = WaitHandle.WaitAny(
            autoEvents, new TimeSpan(0, 0, 3), false);
        if(index == WaitHandle.WaitTimeout)
        {
            Console.WriteLine("\n{0} not found.", fileName);
        }
        else
        {
            Console.WriteLine("\n{0} found on {1}.", fileName,
                diskLetters[index]);
        }
    }

    // Search for stateInfo.fileName.
    void FindCallback(object state)
    {
        State stateInfo = (State)state;

        // Signal if the file is found.
        if(File.Exists(stateInfo.fileName))
        {
            stateInfo.autoEvent.Set();
        }
    }
}
Imports System.IO
Imports System.Threading

Public Class Test

    <MTAThread> _
    Shared Sub Main()
        Dim search As New Search()
        search.FindFile("SomeFile.dat")
    End Sub    
End Class

Public Class Search

    ' Maintain state information to pass to FindCallback.
    Class State
        Public autoEvent As AutoResetEvent 
        Public fileName As String         

        Sub New(anEvent As AutoResetEvent, fName As String)
            autoEvent = anEvent
            fileName = fName
        End Sub
    End Class

    Dim autoEvents() As AutoResetEvent
    Dim diskLetters() As String

    Sub New()

        ' Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives()

        autoEvents = New AutoResetEvent(diskLetters.Length - 1) {}
        For i As Integer = 0 To diskLetters.Length - 1
            autoEvents(i) = New AutoResetEvent(False)
        Next i
    End Sub    
    
    ' Search for fileName in the root directory of all disks.
    Sub FindFile(fileName As String)
        For i As Integer = 0 To diskLetters.Length - 1
            Console.WriteLine("Searching for {0} on {1}.", _
                fileName, diskLetters(i))
        
            ThreadPool.QueueUserWorkItem(AddressOf FindCallback, _ 
                New State(autoEvents(i), diskLetters(i) & fileName))
        Next i

        ' Wait for the first instance of the file to be found.
        Dim index As Integer = WaitHandle.WaitAny( _
            autoEvents, New TimeSpan(0, 0, 3), False)
        If index = WaitHandle.WaitTimeout
            Console.WriteLine(vbCrLf & "{0} not found.", fileName)
        Else
            Console.WriteLine(vbCrLf & "{0} found on {1}.", _
                fileName, diskLetters(index))
        End If
    End Sub

    ' Search for stateInfo.fileName.
    Sub FindCallback(state As Object)
        Dim stateInfo As State = DirectCast(state, State)

        ' Signal if the file is found.
        If File.Exists(stateInfo.fileName) Then
            stateInfo.autoEvent.Set()
        End If
    End Sub

End Class

Remarques

Si timeout est zéro, la méthode ne bloque pas. Il teste l’état des handles d’attente et retourne immédiatement.

La WaitAny méthode lève un AbandonedMutexException uniquement lorsque l’attente se termine en raison d’un mutex abandonné. Si waitHandles contient un mutex libéré avec un numéro d’index inférieur à celui du mutex abandonné, la WaitAny méthode se termine normalement et l’exception n’est pas levée. Un mutex abandonné indique souvent une erreur de codage grave. Dans le cas d’un mutex à l’échelle du système, cela peut indiquer qu’une application a été arrêtée brusquement (par exemple, à l’aide du Gestionnaire des tâches Windows). L’exception contient des informations utiles pour le débogage.

Cette méthode retourne lorsque l’attente se termine, soit lorsque l’un des handles est signalé, soit lorsqu’un délai d’attente se produit. Si plusieurs objets sont signalés pendant l’appel, la valeur de retour est l’index de tableau de l’objet signalé avec la plus petite valeur d’index de tous les objets signalés.

Le nombre maximal de handles d’attente est 64 et 63 si le thread actuel est à STA l’état.

La valeur maximale pour timeout est Int32.MaxValue.

Sortie du contexte

Le exitContext paramètre n’a aucun effet, sauf si cette méthode est appelée à partir d’un contexte managé non par défaut. Le contexte managé peut être non défini par défaut si votre thread se trouve à l’intérieur d’un appel à un instance d’une classe dérivée de ContextBoundObject. Même si vous exécutez actuellement une méthode sur une classe qui n’est pas dérivée de ContextBoundObject, comme String, vous pouvez être dans un contexte non par défaut si un ContextBoundObject se trouve sur votre pile dans le domaine d’application actuel.

Lorsque votre code s’exécute dans un contexte non par défaut, la spécification true pour exitContext entraîne la sortie du thread du contexte managé non par défaut (autrement dit, pour passer au contexte par défaut) avant d’exécuter cette méthode. Le thread retourne au contexte non par défaut d’origine une fois l’appel à cette méthode terminé.

La sortie du contexte peut être utile lorsque la classe liée au contexte a l’attribut SynchronizationAttribute . Dans ce cas, tous les appels aux membres de la classe sont automatiquement synchronisés et le domaine de synchronisation est l’ensemble du corps du code de la classe. Si le code dans la pile d’appels d’un membre appelle cette méthode et spécifie true pour exitContext, le thread quitte le domaine de synchronisation, ce qui permet à un thread bloqué sur un appel à n’importe quel membre de l’objet de continuer. Lorsque cette méthode est retournée, le thread qui a effectué l’appel doit attendre d’être réentrée dans le domaine de synchronisation.

S’applique à