WaitHandle.WaitAny Metoda
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
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.
waitHandles
jest 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.
waitHandles
jest 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.
waitHandles
jest 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.
waitHandles
jest 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.
waitHandles
jest 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.
waitHandles
jest 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.