WaitHandle.WaitAny 메서드

정의

지정된 배열의 모든 요소가 신호를 받기를 기다립니다.

오버로드

WaitAny(WaitHandle[])

지정된 배열의 모든 요소가 신호를 받기를 기다립니다.

WaitAny(WaitHandle[], Int32)

부호 있는 32비트 정수를 사용하여 시간 간격을 지정함으로써 지정된 배열의 임의 요소가 신호를 받기를 기다립니다.

WaitAny(WaitHandle[], TimeSpan)

TimeSpan을 사용하여 시간 간격을 지정함으로써 지정된 배열의 임의 요소가 신호를 받기를 기다립니다.

WaitAny(WaitHandle[], Int32, Boolean)

부호 있는 32비트 정수를 사용하여 시간 간격을 지정하고 대기 전에 동기화 도메인을 종료할지를 지정하여 지정된 배열의 요소가 신호를 받기를 기다립니다.

WaitAny(WaitHandle[], TimeSpan, Boolean)

TimeSpan 값으로 시간 간격을 지정하고 대기 전에 동기화 도메인을 끝낼지 여부를 지정한 다음 지정된 배열의 요소가 신호를 받기를 기다립니다.

WaitAny(WaitHandle[])

지정된 배열의 모든 요소가 신호를 받기를 기다립니다.

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

매개 변수

waitHandles
WaitHandle[]

현재 인스턴스에서 기다릴 개체가 포함된 WaitHandle 배열입니다.

반환

Int32

대기를 만족한 개체의 배열 인덱스입니다.

예외

waitHandles 매개 변수가 null인 경우

또는 waitHandles 배열에 있는 하나 이상의 개체가 null인 경우

waitHandles의 개체 수가 시스템에서 허용하는 것보다 큰 경우

waitHandles가 요소가 없는 배열이고 .NET Framework 버전이 1.0 또는 1.1인 경우

스레드가 뮤텍스를 해제하지 않고 종료되었으므로 대기가 완료되었습니다.

waitHandles을를은 아무런 요소도 갖고 있지 않은 배열이며 .NET Framework 버전은 2.0 이상입니다.

waitHandles 배열에 다른 애플리케이션 도메인에 있는 WaitHandle에 대한 투명 프록시가 포함되어 있습니다.

예제

다음 코드 예제에서는 호출 된 WaitAny 메서드.

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

설명

AbandonedMutexException는 .NET Framework 버전 2.0의 새로운 버전입니다. 이전 버전에서 메서드는 WaitAny true 뮤텍스가 중단 된 경우 대기가 완료 되 면를 반환 합니다. 중단 된 뮤텍스는 종종 심각한 코딩 오류를 나타냅니다. 시스템 차원 뮤텍스의 경우 (예를 들어 Windows 작업 관리자 사용)가 애플리케이션이 갑자기 종료 된 나타낼 수 있습니다. 예외에는 디버깅에 유용한 정보가 포함 되어 있습니다.

WaitAny메서드는 중단 된 AbandonedMutexException mutex로 인해 대기가 완료 될 때만를 throw 합니다. waitHandles에 중단 된 뮤텍스 보다 더 낮은 인덱스 번호가 포함 된 릴리스 뮤텍스가 포함 된 경우 WaitAny 메서드는 정상적으로 완료 되 고 예외가 throw 되지 않습니다.

참고

버전 2.0 이전 버전의 .NET Framework에서 명시적으로를 해제 하지 않고 스레드를 종료 하거나 중단 하 MutexMutex 다른 스레드의 배열에서 인덱스 0 (0)에 있는 경우에 WaitAny 의해 반환 되는 인덱스는 WaitAny 0이 아닌 128입니다.

핸들이 신호를 받으면이 메서드는를 반환 합니다. 호출 하는 동안 두 개 이상의 개체가 신호를 받는 경우 반환 값은 신호를 받은 모든 개체의 인덱스 값이 가장 작은 신호를 받은 개체의 배열 인덱스입니다.

대기 핸들의 최대 수는 64이 고 현재 스레드가 상태인 경우 63입니다 STA .

이 메서드 오버 로드를 호출 하는 것은 WaitAny(WaitHandle[], Int32, Boolean) 메서드 오버 로드를 호출 하 고 Timeout.Infinite millisecondsTimeouttrue 에 대해-1 (또는)를 지정 exitContext 하는 것과 같습니다

적용 대상

WaitAny(WaitHandle[], Int32)

부호 있는 32비트 정수를 사용하여 시간 간격을 지정함으로써 지정된 배열의 임의 요소가 신호를 받기를 기다립니다.

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

매개 변수

waitHandles
WaitHandle[]

현재 인스턴스에서 기다릴 개체가 포함된 WaitHandle 배열입니다.

millisecondsTimeout
Int32

대기할 시간(밀리초)이거나, 무기한 대기할 경우 Infinite(-1)입니다.

반환

Int32

대기를 만족하는 개체의 배열 인덱스이거나 대기를 만족하는 개체가 없고 millisecondsTimeout과 동일한 시간 간격이 전달된 경우 WaitTimeout입니다.

예외

waitHandles 매개 변수가 null인 경우

또는 waitHandles 배열에 있는 하나 이상의 개체가 null인 경우

waitHandles의 개체 수가 시스템에서 허용하는 것보다 큰 경우

millisecondsTimeout이 시간 제한 없음을 나타내는 -1 이외의 음수인 경우

스레드가 뮤텍스를 해제하지 않고 종료되었으므로 대기가 완료되었습니다.

waitHandles가 요소가 없는 배열인 경우

waitHandles 배열에 다른 애플리케이션 도메인에 있는 WaitHandle에 대한 투명 프록시가 포함되어 있습니다.

설명

millisecondsTimeout가 0 인 경우 메서드는 차단 되지 않습니다. 대기 핸들의 상태를 테스트 하 고 즉시 반환 합니다.

WaitAny메서드는 중단 된 AbandonedMutexException mutex로 인해 대기가 완료 될 때만를 throw 합니다. waitHandles에 중단 된 뮤텍스 보다 더 낮은 인덱스 번호가 포함 된 릴리스 뮤텍스가 포함 된 경우 WaitAny 메서드는 정상적으로 완료 되 고 예외가 throw 되지 않습니다.

이 메서드는 핸들이 신호를 받거나 시간 제한이 발생 하는 경우 대기가 종료 될 때를 반환 합니다. 호출 하는 동안 두 개 이상의 개체가 신호를 받는 경우 반환 값은 신호를 받은 모든 개체의 인덱스 값이 가장 작은 신호를 받은 개체의 배열 인덱스입니다.

대기 핸들의 최대 수는 64이 고 현재 스레드가 상태인 경우 63입니다 STA .

이 메서드 오버 로드를 호출 하는 것은 WaitAny(WaitHandle[], Int32, Boolean) 오버 로드를 호출 하 고를 지정 하는 것과 같습니다 false exitContext .

적용 대상

WaitAny(WaitHandle[], TimeSpan)

TimeSpan을 사용하여 시간 간격을 지정함으로써 지정된 배열의 임의 요소가 신호를 받기를 기다립니다.

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

매개 변수

waitHandles
WaitHandle[]

현재 인스턴스에서 기다릴 개체가 포함된 WaitHandle 배열입니다.

timeout
TimeSpan

대기할 시간(밀리초)을 나타내는 TimeSpan이거나, 무한 대기하도록 -1밀리초를 나타내는 TimeSpan입니다.

반환

Int32

대기를 만족하는 개체의 배열 인덱스이거나 대기를 만족하는 개체가 없고 timeout과 동일한 시간 간격이 전달된 경우 WaitTimeout입니다.

예외

waitHandles 매개 변수가 null인 경우

또는 waitHandles 배열에 있는 하나 이상의 개체가 null인 경우

waitHandles의 개체 수가 시스템에서 허용하는 것보다 큰 경우

timeout 은 시간 제한이 없음을 나타내는 -1밀리초 이외의 음수입니다. 또는 timeoutMaxValue보다 큰 경우

스레드가 뮤텍스를 해제하지 않고 종료되었으므로 대기가 완료되었습니다.

waitHandles가 요소가 없는 배열인 경우

waitHandles 배열에 다른 애플리케이션 도메인에 있는 WaitHandle에 대한 투명 프록시가 포함되어 있습니다.

설명

timeout가 0 인 경우 메서드는 차단 되지 않습니다. 대기 핸들의 상태를 테스트 하 고 즉시 반환 합니다.

WaitAny메서드는 중단 된 AbandonedMutexException mutex로 인해 대기가 완료 될 때만를 throw 합니다. waitHandles에 중단 된 뮤텍스 보다 더 낮은 인덱스 번호가 포함 된 릴리스 뮤텍스가 포함 된 경우 WaitAny 메서드는 정상적으로 완료 되 고 예외가 throw 되지 않습니다.

이 메서드는 핸들이 신호를 받거나 제한 시간이 초과 되는 경우 대기가 종료 될 때를 반환 합니다. 호출 하는 동안 두 개 이상의 개체가 신호를 받는 경우 반환 값은 신호를 받은 모든 개체의 인덱스 값이 가장 작은 신호를 받은 개체의 배열 인덱스입니다.

대기 핸들의 최대 수는 64이 고 현재 스레드가 상태인 경우 63입니다 STA .

최대 값은 timeout Int32.MaxValue 입니다.

이 메서드 오버 로드를 호출 하는 것은 WaitAny(WaitHandle[], TimeSpan, Boolean) 오버 로드를 호출 하 고를 지정 하는 것과 같습니다 false exitContext .

적용 대상

WaitAny(WaitHandle[], Int32, Boolean)

부호 있는 32비트 정수를 사용하여 시간 간격을 지정하고 대기 전에 동기화 도메인을 종료할지를 지정하여 지정된 배열의 요소가 신호를 받기를 기다립니다.

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

매개 변수

waitHandles
WaitHandle[]

현재 인스턴스에서 기다릴 개체가 포함된 WaitHandle 배열입니다.

millisecondsTimeout
Int32

대기할 시간(밀리초)이거나, 무기한 대기할 경우 Infinite(-1)입니다.

exitContext
Boolean

대기 전에 컨텍스트에 대한 동기화 도메인을 종료하고(동기화된 컨텍스트에 있는 경우) 이 도메인을 다시 가져오려면 true이고, 그렇지 않으면 false입니다.

반환

Int32

대기를 만족하는 개체의 배열 인덱스이거나 대기를 만족하는 개체가 없고 millisecondsTimeout과 동일한 시간 간격이 전달된 경우 WaitTimeout입니다.

예외

waitHandles 매개 변수가 null인 경우

또는 waitHandles 배열에 있는 하나 이상의 개체가 null인 경우

waitHandles의 개체 수가 시스템에서 허용하는 것보다 큰 경우

waitHandles가 요소가 없는 배열이고 .NET Framework 버전이 1.0 또는 1.1인 경우

millisecondsTimeout이 시간 제한 없음을 나타내는 -1 이외의 음수인 경우

스레드가 뮤텍스를 해제하지 않고 종료되었으므로 대기가 완료되었습니다.

waitHandles을를은 아무런 요소도 갖고 있지 않은 배열이며 .NET Framework 버전은 2.0 이상입니다.

waitHandles 배열에 다른 애플리케이션 도메인에 있는 WaitHandle에 대한 투명 프록시가 포함되어 있습니다.

예제

다음 코드 예제에서는 스레드 풀을 사용하여 여러 디스크에서 파일을 동시에 검색하는 방법을 보여 있습니다. 공간 고려 사항의 경우 각 디스크의 루트 디렉터리만 검색됩니다.

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

설명

millisecondsTimeout가 0이면 메서드가 차단되지 않습니다. 대기 핸들의 상태를 테스트하고 즉시 반환합니다.

AbandonedMutexException는 .NET Framework 버전 2.0의 새로운 버전입니다. 이전 버전에서는 WaitAny true 뮤텍스가 중단되어 대기가 완료되면 메서드가 를 반환합니다. 중단된 뮤텍스는 종종 심각한 코딩 오류를 나타냅니다. 시스템 차원 뮤텍스의 경우 (예를 들어 Windows 작업 관리자 사용)가 애플리케이션이 갑자기 종료 된 나타낼 수 있습니다. 예외에는 디버깅에 유용한 정보가 포함되어 있습니다.

WaitAny메서드는 AbandonedMutexException 중단된 뮤텍스로 인해 대기가 완료될 때만 을 throw합니다. waitHandles에 중단된 뮤텍스보다 인덱스 번호가 낮은 해제된 뮤텍스가 포함된 경우 WaitAny 메서드가 정상적으로 완료되고 예외가 throw되지 않습니다.

참고

버전 2.0 이전의 .NET Framework 버전에서 스레드가 를 명시적으로 해제하지 않고 종료되거나 Mutex 중단되고 Mutex 다른 스레드의 배열에서 인덱스 0에 있는 경우 에서 WaitAny 반환된 인덱스는 WaitAny 0이 아닌 128입니다.

이 메서드는 핸들 중 하나가 신호를 받거나 시간 초과가 발생할 때 대기가 종료될 때 를 반환합니다. 호출 중에 두 개 이상의 개체가 신호를 받으면 반환 값은 신호를 받은 모든 개체의 인덱스 값이 가장 작은 신호를 받은 개체의 배열 인덱스입니다.

대기 핸들의 최대 수는 64이고 현재 스레드가 상태이면 STA 63입니다.

컨텍스트 종료에 대한 참고 사항

exitContext매개 변수는 WaitAny 메서드가 비기본 관리 컨텍스트 내에서 호출되지 않는 한 아무런 영향을 미치지 않습니다. 스레드가 에서 파생된 클래스의 인스턴스에 대한 호출 내에 있는 경우에 발생할 수 ContextBoundObject 있습니다. 파생 되지 않은 클래스에 메서드를 현재 실행 중인 경우에 ContextBoundObject같은 String, 기본이 아닌 컨텍스트에서 할 경우를 ContextBoundObject 가 현재 애플리케이션 도메인에서 스택에 합니다.

코드가 기본이 아닌 컨텍스트에서 실행되는 경우 true 에 을 exitContext 지정하면 메서드를 실행하기 전에 스레드가 기본이 아닌 관리되는 컨텍스트(즉, 기본 컨텍스트로 전환)를 WaitAny 종료합니다. 메서드 호출이 완료된 후 스레드가 원래의 비기본 컨텍스트로 WaitAny 돌아갑니다.

컨텍스트 바인딩된 클래스에 가 있는 경우에 유용할 수 SynchronizationAttribute 있습니다. 이 경우 클래스의 멤버에 대한 모든 호출이 자동으로 동기화되고 동기화 도메인은 클래스에 대한 코드의 전체 본문입니다. 멤버의 호출 스택에 있는 코드가 WaitAny 메서드를 호출하고 에 대해 를 지정하는 경우 true exitContext 스레드는 동기화 도메인을 종료하여 개체의 모든 멤버에 대한 호출에서 차단된 스레드가 계속 진행되도록 합니다. WaitAny메서드가 반환되면 호출한 스레드가 동기화 도메인을 다시 활성화하기 위해 대기해야 합니다.

적용 대상

WaitAny(WaitHandle[], TimeSpan, Boolean)

TimeSpan 값으로 시간 간격을 지정하고 대기 전에 동기화 도메인을 끝낼지 여부를 지정한 다음 지정된 배열의 요소가 신호를 받기를 기다립니다.

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

매개 변수

waitHandles
WaitHandle[]

현재 인스턴스에서 기다릴 개체가 포함된 WaitHandle 배열입니다.

timeout
TimeSpan

대기할 시간(밀리초)을 나타내는 TimeSpan이거나, 무한 대기하도록 -1밀리초를 나타내는 TimeSpan입니다.

exitContext
Boolean

대기 전에 컨텍스트에 대한 동기화 도메인을 종료하고(동기화된 컨텍스트에 있는 경우) 이 도메인을 다시 가져오려면 true이고, 그렇지 않으면 false입니다.

반환

Int32

대기를 만족하는 개체의 배열 인덱스이거나 대기를 만족하는 개체가 없고 timeout과 동일한 시간 간격이 전달된 경우 WaitTimeout입니다.

예외

waitHandles 매개 변수가 null인 경우

또는 waitHandles 배열에 있는 하나 이상의 개체가 null인 경우

waitHandles의 개체 수가 시스템에서 허용하는 것보다 큰 경우

waitHandles가 요소가 없는 배열이고 .NET Framework 버전이 1.0 또는 1.1인 경우

timeout 은 시간 제한이 없음을 나타내는 -1밀리초 이외의 음수입니다. 또는 timeoutMaxValue보다 큰 경우

스레드가 뮤텍스를 해제하지 않고 종료되었으므로 대기가 완료되었습니다.

waitHandles을를은 아무런 요소도 갖고 있지 않은 배열이며 .NET Framework 버전은 2.0 이상입니다.

waitHandles 배열에 다른 애플리케이션 도메인에 있는 WaitHandle에 대한 투명 프록시가 포함되어 있습니다.

예제

다음 코드 예제에서는 스레드 풀을 사용하여 여러 디스크에서 파일을 동시에 검색하는 방법을 보여 있습니다. 공간 고려 사항의 경우 각 디스크의 루트 디렉터리만 검색됩니다.

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

설명

timeout가 0이면 메서드가 차단되지 않습니다. 대기 핸들의 상태를 테스트하고 즉시 반환합니다.

AbandonedMutexException는 .NET Framework 버전 2.0의 새로운 버전입니다. 이전 버전에서는 WaitAny true 뮤텍스가 중단되어 대기가 완료되면 메서드가 를 반환합니다. 중단된 뮤텍스는 종종 심각한 코딩 오류를 나타냅니다. 시스템 차원 뮤텍스의 경우 (예를 들어 Windows 작업 관리자 사용)가 애플리케이션이 갑자기 종료 된 나타낼 수 있습니다. 예외에는 디버깅에 유용한 정보가 포함되어 있습니다.

WaitAny메서드는 AbandonedMutexException 중단된 뮤텍스로 인해 대기가 완료될 때만 을 throw합니다. waitHandles에 중단된 뮤텍스보다 인덱스 번호가 낮은 해제된 뮤텍스가 포함된 경우 WaitAny 메서드가 정상적으로 완료되고 예외가 throw되지 않습니다.

참고

버전 2.0 이전의 .NET Framework 버전에서 스레드가 를 명시적으로 해제하지 않고 종료되거나 Mutex 중단되고 Mutex 다른 스레드의 배열에서 인덱스 0에 있는 경우 에서 WaitAny 반환된 인덱스는 WaitAny 0이 아닌 128입니다.

이 메서드는 핸들 중 하나가 신호를 받거나 시간 중단이 발생할 때 대기가 종료될 때 를 반환합니다. 호출 중에 두 개 이상의 개체가 신호를 받으면 반환 값은 신호를 받은 모든 개체의 인덱스 값이 가장 작은 신호를 받은 개체의 배열 인덱스입니다.

대기 핸들의 최대 수는 64이고 현재 스레드가 상태이면 STA 63입니다.

timeout 최대값은 Int32.MaxValue 입니다.

컨텍스트 종료에 대한 참고 사항

exitContext매개 변수는 WaitAny 메서드가 비기본 관리 컨텍스트 내에서 호출되지 않는 한 아무런 영향을 미치지 않습니다. 스레드가 에서 파생된 클래스의 인스턴스에 대한 호출 내에 있는 경우에 발생할 수 ContextBoundObject 있습니다. 파생 되지 않은 클래스에 메서드를 현재 실행 중인 경우에 ContextBoundObject같은 String, 기본이 아닌 컨텍스트에서 할 경우를 ContextBoundObject 가 현재 애플리케이션 도메인에서 스택에 합니다.

코드가 기본이 아닌 컨텍스트에서 실행되는 경우 true 에 을 exitContext 지정하면 메서드를 실행하기 전에 스레드가 기본이 아닌 관리되는 컨텍스트(즉, 기본 컨텍스트로 전환)를 WaitAny 종료합니다. 메서드 호출이 완료된 후 스레드가 원래의 비기본 컨텍스트로 WaitAny 돌아갑니다.

컨텍스트 바인딩된 클래스에 가 있는 경우에 유용할 수 SynchronizationAttribute 있습니다. 이 경우 클래스의 멤버에 대한 모든 호출이 자동으로 동기화되고 동기화 도메인은 클래스에 대한 코드의 전체 본문입니다. 멤버의 호출 스택에 있는 코드가 WaitAny 메서드를 호출하고 에 대해 를 지정하는 경우 true exitContext 스레드는 동기화 도메인을 종료하여 개체의 모든 멤버에 대한 호출에서 차단된 스레드가 계속 진행되도록 합니다. WaitAny메서드가 반환되면 호출한 스레드가 동기화 도메인을 다시 활성화하기 위해 대기해야 합니다.

적용 대상