WaitHandle.WaitAny Metoda

Definicja

Oczekuje na odebranie sygnału przez dowolny element w określonej tablicy.

Przeciążenia

WaitAny(WaitHandle[])

Oczekuje na odebranie sygnału przez dowolny element w określonej tablicy.

WaitAny(WaitHandle[], Int32)

Oczekuje, aż dowolny element w określonej tablicy otrzyma sygnał, używając 32-bitowej liczby całkowitej ze znakiem w celu określenia interwału czasu.

WaitAny(WaitHandle[], TimeSpan)

Oczekuje na odebranie sygnału przez dowolny element w określonej tablicy przy użyciu parametru , TimeSpan aby określić przedział czasu.

WaitAny(WaitHandle[], Int32, Boolean)

Oczekuje, aż dowolny element w określonej tablicy otrzyma sygnał, używając 32-bitowej liczby całkowitej ze znakiem w celu określenia interwału czasu i określenia, czy należy zamknąć domenę synchronizacji przed oczekiwaniem.

WaitAny(WaitHandle[], TimeSpan, Boolean)

Oczekuje na odebranie sygnału przez dowolny element w określonej tablicy przy użyciu parametru w TimeSpan celu określenia przedziału czasu i określenia, czy należy zamknąć domenę synchronizacji przed oczekiwaniem.

WaitAny(WaitHandle[])

Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs

Oczekuje na odebranie sygnału przez dowolny element w określonej tablicy.

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

Parametry

waitHandles
WaitHandle[]

Tablica WaitHandle zawierająca obiekty, dla których będzie czekać bieżące wystąpienie.

Zwraca

Indeks tablicy obiektu spełniającego oczekiwania.

Wyjątki

Parametr waitHandles ma wartość null.

-lub-

Co najmniej jeden obiekt w tablicy waitHandles to null.

Liczba obiektów w obiekcie waitHandles jest większa niż zezwala system.

waitHandlesjest tablicą bez elementów, a wersja .NET Framework to 1.0 lub 1.1.

Oczekiwanie zostało ukończone, ponieważ wątek zakończył się bez zwolnienia mutexu.

waitHandlesjest tablicą bez elementów, a .NET Framework w wersji 2.0 lub nowszej.

Tablica waitHandles zawiera przezroczysty serwer proxy dla obiektu WaitHandle w innej domenie aplikacji.

Przykłady

W poniższym przykładzie kodu pokazano wywołanie WaitAny metody .

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).

Uwagi

AbandonedMutexExceptionjest nowy w .NET Framework w wersji 2.0. W poprzednich wersjach WaitAny metoda zwraca true wartość , jeśli oczekiwanie zostanie zakończone, ponieważ porzucany jest mutex. Porzucony mutex często wskazuje poważny błąd kodowania. W przypadku całego systemu mutex może wskazywać, że aplikacja została nagle zakończona (na przykład za pomocą Menedżera zadań systemu Windows). Wyjątek zawiera informacje przydatne do debugowania.

Metoda WaitAny zgłasza wyjątek tylko wtedy, gdy oczekiwanie AbandonedMutexException zostanie zakończone z powodu porzuconego mutexu. Jeśli waitHandles zawiera zwolniony mutex z niższym numerem indeksu niż porzucony mutex, WaitAny metoda kończy się normalnie i wyjątek nie jest zgłaszany.

Uwaga

W wersjach .NET Framework starszych niż wersja 2.0, jeśli wątek kończy się lub przerywa bez jawnego zwolnienia Mutex, i to Mutex jest w indeksie 0 (zero) w tablicy w WaitAny innym wątku, indeks zwracany przez WaitAny jest 128 zamiast 0.

Ta metoda zwraca informację, gdy zostanie zasygnalizowana dowolna obsługa. Jeśli podczas wywołania zasygnalizuje się więcej niż jeden obiekt, zwracana wartość jest indeksem tablicy sygnalizowanego obiektu z najmniejszą wartością indeksu wszystkich zasygnaliowanych obiektów.

Maksymalna liczba dojść oczekiwania wynosi 64 i 63, jeśli bieżący wątek jest w STA stanie .

Wywoływanie tego przeciążenia metody jest równoważne wywołaniu przeciążenia metody i określeniu WaitAny(WaitHandle[], Int32, Boolean) parametru -1 (lub Timeout.Infinite) dla parametru millisecondsTimeout i true dla exitContext.

Dotyczy

WaitAny(WaitHandle[], Int32)

Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs

Oczekuje, aż dowolny element w określonej tablicy otrzyma sygnał, używając 32-bitowej liczby całkowitej ze znakiem w celu określenia interwału czasu.

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

Parametry

waitHandles
WaitHandle[]

Tablica WaitHandle zawierająca obiekty, dla których będzie czekać bieżące wystąpienie.

millisecondsTimeout
Int32

Liczba milisekund oczekiwania lub Infinite (-1) oczekiwania na czas nieokreślony.

Zwraca

Indeks tablicy obiektu, który spełnia oczekiwania, lub WaitTimeout jeśli żaden obiekt nie spełnia oczekiwania i interwał czasu równoważny millisecondsTimeout z upływem.

Wyjątki

Parametr waitHandles ma wartość null.

-lub-

Co najmniej jeden obiekt w tablicy waitHandles to null.

Liczba obiektów w obiekcie waitHandles jest większa niż zezwala system.

millisecondsTimeout jest liczbą ujemną inną niż -1, która reprezentuje nieskończony limit czasu.

Oczekiwanie zostało ukończone, ponieważ wątek zakończył się bez zwolnienia mutexu.

waitHandles jest tablicą bez elementów.

Tablica waitHandles zawiera przezroczysty serwer proxy dla obiektu WaitHandle w innej domenie aplikacji.

Uwagi

Jeśli millisecondsTimeout wartość jest równa zero, metoda nie blokuje. Testuje stan uchwytów oczekiwania i zwraca natychmiast.

Metoda WaitAny zgłasza wyjątek tylko wtedy, gdy oczekiwanie AbandonedMutexException zostanie zakończone z powodu porzuconego mutexu. Jeśli waitHandles zawiera zwolniony mutex z niższym numerem indeksu niż porzucony mutex, WaitAny metoda kończy się normalnie i wyjątek nie jest zgłaszany.

Ta metoda zwraca informację o zakończeniu oczekiwania, gdy którykolwiek z dojść jest zasygnalizowany lub gdy wystąpi przekroczenie limitu czasu. Jeśli podczas wywołania zasygnalizuje się więcej niż jeden obiekt, zwracana wartość jest indeksem tablicy sygnalizowanego obiektu z najmniejszą wartością indeksu wszystkich zasygnaliowanych obiektów.

Maksymalna liczba dojść oczekiwania wynosi 64 i 63, jeśli bieżący wątek jest w STA stanie .

Wywoływanie tego przeciążenia metody jest takie samo jak wywoływanie WaitAny(WaitHandle[], Int32, Boolean) przeciążenia i określanie false parametru .exitContext

Dotyczy

WaitAny(WaitHandle[], TimeSpan)

Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs

Oczekuje na odebranie sygnału przez dowolny element w określonej tablicy przy użyciu parametru , TimeSpan aby określić przedział czasu.

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

Parametry

waitHandles
WaitHandle[]

Tablica WaitHandle zawierająca obiekty, dla których będzie czekać bieżące wystąpienie.

timeout
TimeSpan

Wartość TimeSpan reprezentująca liczbę milisekund oczekiwania lub wartość reprezentująca TimeSpan -1 milisekundy oczekiwania na czas nieokreślony.

Zwraca

Indeks tablicy obiektu, który spełnia oczekiwania, lub WaitTimeout jeśli żaden obiekt nie spełnia oczekiwania i interwał czasu równoważny timeout z upływem.

Wyjątki

Parametr waitHandles ma wartość null.

-lub-

Co najmniej jeden obiekt w tablicy waitHandles to null.

Liczba obiektów w obiekcie waitHandles jest większa niż zezwala system.

timeout jest liczbą ujemną inną niż -1 milisekundy, która reprezentuje nieskończony limit czasu.

-lub-

timeout parametr jest większy niż Int32.MaxValue.

Oczekiwanie zostało ukończone, ponieważ wątek zakończył się bez zwolnienia mutexu.

waitHandles jest tablicą bez elementów.

Tablica waitHandles zawiera przezroczysty serwer proxy dla obiektu WaitHandle w innej domenie aplikacji.

Uwagi

Jeśli timeout wartość jest równa zero, metoda nie blokuje. Testuje stan uchwytów oczekiwania i zwraca natychmiast.

Metoda WaitAny zgłasza wyjątek tylko wtedy, gdy oczekiwanie AbandonedMutexException zostanie zakończone z powodu porzuconego mutexu. Jeśli waitHandles zawiera zwolniony mutex z niższym numerem indeksu niż porzucony mutex, WaitAny metoda kończy się normalnie i wyjątek nie jest zgłaszany.

Ta metoda zwraca informację o zakończeniu oczekiwania, gdy którykolwiek z dojść jest zasygnalizowany lub gdy wystąpi przekroczenie limitu czasu. Jeśli podczas wywołania zasygnalizuje się więcej niż jeden obiekt, zwracana wartość jest indeksem tablicy sygnalizowanego obiektu z najmniejszą wartością indeksu wszystkich zasygnaliowanych obiektów.

Maksymalna liczba dojść oczekiwania wynosi 64 i 63, jeśli bieżący wątek jest w STA stanie .

Wartość maksymalna dla parametru timeout to Int32.MaxValue.

Wywoływanie tego przeciążenia metody jest takie samo jak wywoływanie WaitAny(WaitHandle[], TimeSpan, Boolean) przeciążenia i określanie false parametru .exitContext

Dotyczy

WaitAny(WaitHandle[], Int32, Boolean)

Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs

Oczekuje, aż dowolny element w określonej tablicy otrzyma sygnał, używając 32-bitowej liczby całkowitej ze znakiem w celu określenia interwału czasu i określenia, czy należy zamknąć domenę synchronizacji przed oczekiwaniem.

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

Parametry

waitHandles
WaitHandle[]

Tablica WaitHandle zawierająca obiekty, dla których będzie czekać bieżące wystąpienie.

millisecondsTimeout
Int32

Liczba milisekund oczekiwania lub Infinite (-1) oczekiwania na czas nieokreślony.

exitContext
Boolean

true aby zamknąć domenę synchronizacji dla kontekstu przed oczekiwaniem (jeśli w zsynchronizowanym kontekście) i ponownie go później; w przeciwnym razie , false.

Zwraca

Indeks tablicy obiektu, który spełnia oczekiwania, lub WaitTimeout jeśli żaden obiekt nie spełnia oczekiwania i interwał czasu równoważny millisecondsTimeout z upływem.

Wyjątki

Parametr waitHandles ma wartość null.

-lub-

Co najmniej jeden obiekt w tablicy waitHandles to null.

Liczba obiektów w obiekcie waitHandles jest większa niż zezwala system.

waitHandlesjest tablicą bez elementów, a wersja .NET Framework to 1.0 lub 1.1.

millisecondsTimeout jest liczbą ujemną inną niż -1, która reprezentuje nieskończony limit czasu.

Oczekiwanie zostało ukończone, ponieważ wątek zakończył się bez zwolnienia mutexu.

waitHandlesjest tablicą bez elementów, a .NET Framework w wersji 2.0 lub nowszej.

Tablica waitHandles zawiera przezroczysty serwer proxy dla obiektu WaitHandle w innej domenie aplikacji.

Przykłady

W poniższym przykładzie kodu pokazano, jak używać puli wątków do jednoczesnego wyszukiwania pliku na wielu dyskach. W przypadku zagadnień dotyczących miejsca przeszukiwany jest tylko katalog główny każdego dysku.

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

Uwagi

Jeśli millisecondsTimeout wartość jest równa zero, metoda nie blokuje. Testuje stan uchwytów oczekiwania i zwraca natychmiast.

Metoda WaitAny zgłasza wyjątek tylko wtedy, gdy oczekiwanie AbandonedMutexException zostanie zakończone z powodu porzuconego mutexu. Jeśli waitHandles zawiera zwolniony mutex z niższym numerem indeksu niż porzucony mutex, WaitAny metoda kończy się normalnie i wyjątek nie jest zgłaszany. Porzucony mutex często wskazuje poważny błąd kodowania. W przypadku całego systemu mutex może wskazywać, że aplikacja została nagle zakończona (na przykład za pomocą Menedżera zadań systemu Windows). Wyjątek zawiera informacje przydatne do debugowania.

Ta metoda zwraca informację o zakończeniu oczekiwania, gdy którykolwiek z dojść jest zasygnalizowany lub gdy wystąpi przekroczenie limitu czasu. Jeśli podczas wywołania zasygnalizuje się więcej niż jeden obiekt, zwracana wartość jest indeksem tablicy sygnalizowanego obiektu z najmniejszą wartością indeksu wszystkich zasygnaliowanych obiektów.

Maksymalna liczba dojść oczekiwania wynosi 64 i 63, jeśli bieżący wątek jest w STA stanie .

Zamykanie kontekstu

Parametr exitContext nie ma wpływu, chyba że ta metoda jest wywoływana z wewnątrz kontekstu zarządzanego bez definicji. Kontekst zarządzany może być niezdefault, jeśli wątek znajduje się wewnątrz wywołania do wystąpienia klasy pochodzącej z ContextBoundObjectklasy . Nawet jeśli obecnie wykonujesz metodę w klasie, która nie pochodzi z ContextBoundObjectklasy , na przykład String, możesz znajdować się w kontekście niedefault, jeśli element ContextBoundObject znajduje się na stosie w bieżącej domenie aplikacji.

Gdy kod jest wykonywany w kontekście niedefault, określając true , że exitContext wątek ma zamknąć niedefaultowy kontekst zarządzany (tj. przejść do kontekstu domyślnego) przed wykonaniem tej metody. Po zakończeniu wywołania tej metody wątek powraca do oryginalnego kontekstu niezdefaultowego.

Zamknięcie kontekstu może być przydatne, gdy klasa powiązana kontekstem SynchronizationAttribute ma atrybut . W takim przypadku wszystkie wywołania elementów członkowskich klasy są automatycznie synchronizowane, a domena synchronizacji jest całą treścią kodu dla klasy. Jeśli kod w stosie wywołań elementu członkowskiego wywołuje tę metodę i określa true metodę exitContext, wątek kończy domenę synchronizacji, co umożliwia kontynuowanie wątku, który jest blokowany w wywołaniu dowolnego elementu członkowskiego obiektu. Gdy ta metoda powróci, wątek, który wykonał wywołanie, musi poczekać na ponowne włączenie domeny synchronizacji.

Dotyczy

WaitAny(WaitHandle[], TimeSpan, Boolean)

Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs
Źródło:
WaitHandle.cs

Oczekuje na odebranie sygnału przez dowolny element w określonej tablicy przy użyciu parametru w TimeSpan celu określenia przedziału czasu i określenia, czy należy zamknąć domenę synchronizacji przed oczekiwaniem.

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

Parametry

waitHandles
WaitHandle[]

Tablica WaitHandle zawierająca obiekty, dla których będzie czekać bieżące wystąpienie.

timeout
TimeSpan

Wartość TimeSpan reprezentująca liczbę milisekund oczekiwania lub wartość reprezentująca TimeSpan -1 milisekundy oczekiwania na czas nieokreślony.

exitContext
Boolean

true aby zamknąć domenę synchronizacji dla kontekstu przed oczekiwaniem (jeśli w zsynchronizowanym kontekście) i ponownie go później; w przeciwnym razie , false.

Zwraca

Indeks tablicy obiektu, który spełnia oczekiwania, lub WaitTimeout jeśli żaden obiekt nie spełnia oczekiwania i interwał czasu równoważny timeout z upływem.

Wyjątki

Parametr waitHandles ma wartość null.

-lub-

Co najmniej jeden obiekt w tablicy waitHandles to null.

Liczba obiektów w obiekcie waitHandles jest większa niż zezwala system.

waitHandlesjest tablicą bez elementów, a wersja .NET Framework to 1.0 lub 1.1.

timeout jest liczbą ujemną inną niż -1 milisekundy, która reprezentuje nieskończony limit czasu.

-lub-

timeout parametr jest większy niż Int32.MaxValue.

Oczekiwanie zostało ukończone, ponieważ wątek zakończył się bez zwolnienia mutexu.

waitHandlesjest tablicą bez elementów, a .NET Framework w wersji 2.0 lub nowszej.

Tablica waitHandles zawiera przezroczysty serwer proxy dla obiektu WaitHandle w innej domenie aplikacji.

Przykłady

W poniższym przykładzie kodu pokazano, jak używać puli wątków do jednoczesnego wyszukiwania pliku na wielu dyskach. W przypadku zagadnień dotyczących miejsca przeszukiwany jest tylko katalog główny każdego dysku.

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

Uwagi

Jeśli timeout wartość jest równa zero, metoda nie blokuje. Testuje stan uchwytów oczekiwania i zwraca natychmiast.

Metoda WaitAny zgłasza wyjątek tylko wtedy, gdy oczekiwanie AbandonedMutexException zostanie zakończone z powodu porzuconego mutexu. Jeśli waitHandles zawiera zwolniony mutex z niższym numerem indeksu niż porzucony mutex, WaitAny metoda kończy się normalnie i wyjątek nie jest zgłaszany. Porzucony mutex często wskazuje poważny błąd kodowania. W przypadku całego systemu mutex może wskazywać, że aplikacja została nagle zakończona (na przykład za pomocą Menedżera zadań systemu Windows). Wyjątek zawiera informacje przydatne do debugowania.

Ta metoda zwraca informację o zakończeniu oczekiwania, gdy którykolwiek z dojść jest zasygnalizowany lub gdy wystąpi przekroczenie limitu czasu. Jeśli podczas wywołania zasygnalizuje się więcej niż jeden obiekt, zwracana wartość jest indeksem tablicy sygnalizowanego obiektu z najmniejszą wartością indeksu wszystkich zasygnaliowanych obiektów.

Maksymalna liczba dojść oczekiwania wynosi 64 i 63, jeśli bieżący wątek jest w STA stanie .

Wartość maksymalna dla parametru timeout to Int32.MaxValue.

Zamykanie kontekstu

Parametr exitContext nie ma wpływu, chyba że ta metoda jest wywoływana z wewnątrz kontekstu zarządzanego bez definicji. Kontekst zarządzany może być niezdefault, jeśli wątek znajduje się wewnątrz wywołania do wystąpienia klasy pochodzącej z ContextBoundObjectklasy . Nawet jeśli obecnie wykonujesz metodę w klasie, która nie pochodzi z ContextBoundObjectklasy , na przykład String, możesz znajdować się w kontekście niedefault, jeśli element ContextBoundObject znajduje się na stosie w bieżącej domenie aplikacji.

Gdy kod jest wykonywany w kontekście niedefault, określając true , że exitContext wątek ma zamknąć niedefaultowy kontekst zarządzany (tj. przejść do kontekstu domyślnego) przed wykonaniem tej metody. Po zakończeniu wywołania tej metody wątek powraca do oryginalnego kontekstu niezdefaultowego.

Zamknięcie kontekstu może być przydatne, gdy klasa powiązana kontekstem SynchronizationAttribute ma atrybut . W takim przypadku wszystkie wywołania elementów członkowskich klasy są automatycznie synchronizowane, a domena synchronizacji jest całą treścią kodu dla klasy. Jeśli kod w stosie wywołań elementu członkowskiego wywołuje tę metodę i określa true metodę exitContext, wątek kończy domenę synchronizacji, co umożliwia kontynuowanie wątku, który jest blokowany w wywołaniu dowolnego elementu członkowskiego obiektu. Gdy ta metoda powróci, wątek, który wykonał wywołanie, musi poczekać na ponowne włączenie domeny synchronizacji.

Dotyczy