이 페이지가 유용했습니까?
이 콘텐츠에 대한 여러분의 의견은 중요합니다. 의견을 알려주십시오.
추가 의견
1500자 남음
MSDN Library
정보
요청한 주제가 아래에 표시됩니다. 그러나 이 주제는 이 라이브러리에 포함되지 않습니다.

WaitHandle 클래스

2013-12-13

공유 리소스에 대한 단독 액세스를 기다리는 운영 체제 관련 개체를 캡슐화합니다.

Namespace:  System.Threading
어셈블리:  mscorlib(mscorlib.dll)

public abstract class WaitHandle : IDisposable

WaitHandle 형식에서는 다음과 같은 멤버를 노출합니다.

  이름설명
Protected 메서드WaitHandleWaitHandle 클래스의 새 인스턴스를 초기화합니다.
맨 위

  이름설명
Public 속성SafeWaitHandle네이티브 운영 체제 핸들을 가져오거나 설정합니다.
맨 위

  이름설명
Public 메서드Close파생 클래스에서 재정의될 때 현재 WaitHandle에서 보유한 모든 리소스를 해제합니다.
Public 메서드Dispose()WaitHandle 클래스의 현재 인스턴스에서 사용하는 모든 리소스를 해제합니다.
Protected 메서드Dispose(Boolean)파생 클래스에서 재정의된 경우 WaitHandle에서 사용하는 관리되지 않는 리소스를 해제하고 필요에 따라 관리되는 리소스를 해제합니다.
Public 메서드Equals(Object)지정한 Object가 현재 Object와 같은지 확인합니다. (Object에서 상속됨)
Protected 메서드Finalize가비지 수집기에서 Object를 회수하기 전에 개체가 리소스를 해제하고 다른 정리 작업을 수행할 수 있게 합니다. (Object에서 상속됨)
Public 메서드GetHashCode특정 형식에 대한 해시 함수 역할을 합니다. (Object에서 상속됨)
Public 메서드GetType현재 인스턴스의 Type을 가져옵니다. (Object에서 상속됨)
Protected 메서드MemberwiseClone현재 Object의 단순 복사본을 만듭니다. (Object에서 상속됨)
Public 메서드ToString현재 개체를 나타내는 문자열을 반환합니다. (Object에서 상속됨)
Public 메서드정적 멤버WaitAll(WaitHandle[])지정된 배열의 모든 요소가 신호를 받기를 기다립니다.
Public 메서드정적 멤버WaitAll(WaitHandle[], Int32)Int32 값을 사용하여 시간 간격을 지정하면서 지정된 배열의 모든 요소가 신호를 받기를 기다립니다.
Public 메서드정적 멤버WaitAll(WaitHandle[], TimeSpan)TimeSpan 값을 사용하여 시간 간격을 지정하면서 지정된 배열의 모든 요소가 신호를 받기를 기다립니다.
Public 메서드정적 멤버WaitAny(WaitHandle[])지정된 배열의 모든 요소가 신호를 받기를 기다립니다.
Public 메서드정적 멤버WaitAny(WaitHandle[], Int32)부호 있는 32비트 정수를 사용하여 시간 간격을 지정하고 지정된 배열의 임의 요소가 신호를 받기를 기다립니다.
Public 메서드정적 멤버WaitAny(WaitHandle[], TimeSpan)TimeSpan을 사용하여 시간 간격을 지정하면서 지정된 배열의 임의 요소가 신호를 받기를 기다립니다.
Public 메서드WaitOne()현재 WaitHandle이 신호를 받을 때까지 현재 스레드를 차단합니다.
Public 메서드WaitOne(Int32)부호 있는 32비트 정수를 사용하여 시간 간격을 지정하고 현재 WaitHandle이 신호를 받을 때까지 현재 스레드를 차단합니다.
Public 메서드WaitOne(TimeSpan)TimeSpan을 사용하여 시간 간격을 측정하면서 현재 인스턴스가 신호를 받을 때까지 현재 스레드를 차단합니다.
맨 위

  이름설명
Protected 필드정적 멤버InvalidHandle유효하지 않은 네이티브 운영 체제 핸들을 나타냅니다. 이 필드는 읽기 전용입니다.
Public 필드정적 멤버WaitTimeout대기 핸들이 신호를 받기 전에 WaitAny 작업이 제한 시간을 초과했음을 나타냅니다. 이 필드는 상수입니다.
맨 위

이 클래스는 일반적으로 동기화 개체의 기본 클래스로 사용됩니다. WaitHandle에서 파생된 클래스는 공유 리소스에 대한 액세스 또는 액세스 해제를 나타내는 신호 메커니즘을 정의하지만 공유 리소스에 대한 액세스를 기다리는 동안 상속된 WaitHandle 메서드를 사용하여 차단합니다. Windows Phone에서 AutoResetEventManualResetEvent 클래스는 해당 기본 클래스 EventWaitHandle과 함께 WaitHandle에서 파생됩니다.

이 클래스의 정적 메서드를 사용하여 하나 이상의 동기화 개체에서 신호를 받을 때까지 차단하세요.

다음 예제에서는 작업을 세 개의 스레드 풀 스레드로 나누는 방법과, 정적 메서드 WaitAnyWaitAll을 사용하여 하위 작업이 끝날 때까지 기다리는 방법을 보여 줍니다.

이 예제에서는 사용자 인터페이스에 진행률을 보고하는 BackgroundWorker를 만듭니다. 그런 다음 BackgroundWorker를 사용하여 사용자 인터페이스 스레드가 WaitAnyWaitAll 메서드에 영향을 받지 않도록 하여 사용자 인터페이스가 계속 응답할 수 있도록 합니다.

BackgroundWorkerThreadPool.QueueUserWorkItem 메서드를 사용하여 세 개의 작업을 만들고 각 작업에 임의의 작업량을 할당하는 DoWork 메서드를 실행합니다. 이 예제에서는 각 작업에 대한 데이터와 스레드 프로시저를 보유하는 Subtask 클래스를 정의합니다. 각 작업에는 작업이 완료되면 신호를 보내는 ManualResetEvent가 포함되어 있습니다.

작업이 시작되면 DoWork 메서드에서 WaitAny(WaitHandle[], Int32) 메서드 오버로드를 사용하여 가장 짧은 하위 작업이 끝나기를 기다리며 이때 사용자 인터페이스에 진행률을 보고하는 제한 시간은 250밀리초입니다. 그런 후 BackgroundWorker에서는 WaitAll(WaitHandle[], Int32) 메서드 오버로드를 사용하여 나머지 작업이 완료될 때까지 기다리며, 이때도 제한 시간을 사용하여 진행률을 표시합니다. 그런 다음 DoWork 메서드가 세 작업의 결과를 모두 사용하여 보고서를 생성합니다.

참고참고:

가장 짧은 작업이 가장 먼저 완료되지 않을 수도 있습니다. 스레드 풀 스레드 중 일부는 즉시 시작되지 않을 수도 있고 스케줄러에서 동등하게 처리되지 않을 수도 있습니다.

예제를 시작하면 예제에서 사용자 클릭이 표시되도록 마우스 단추 이벤트를 변경하여 백그라운드 작업 실행 중 사용자 인터페이스가 응답 상태를 유지하는 것을 보여 줍니다.

참고참고:

이 예제를 실행하려면 Windows Phone용 정적 TextBlock 컨트롤이 있는 예제 빌드를 참조하세요.


using System;
using System.Threading;

// The following using statements simplify the supporting code; they are not required 
// for WaitHandle:
using System.Windows.Controls;
using System.Windows.Input;
using System.ComponentModel;

public class Example
{
   private static TextBlock outputBlock;

   public static void Demo(TextBlock outputBlock)
   {
      Example.outputBlock = outputBlock;
      Example.outputBlock.Text = "Click to start the demo.";

      outputBlock.MouseLeftButtonUp += new MouseButtonEventHandler(MouseUpStart);
   }

   private static void MouseUpStart(object sender, MouseEventArgs e)
   {
      // Replace the startup mouse button handler with a handler that 
      // displays a message.
      outputBlock.MouseLeftButtonUp -= new MouseButtonEventHandler(MouseUpStart);
      outputBlock.MouseLeftButtonUp += new MouseButtonEventHandler(MouseUp);

      outputBlock.Text = 
         "Demo is running. The BackgroundWorker waits for the first subtask to complete,\n" +
         "then waits for all subtasks to complete and produces a report.\n" +
         "Click here at any time to show that the user interface is responsive.\n";

      System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
      worker.DoWork += DoWork;
      worker.WorkerReportsProgress = true;
      worker.ProgressChanged += Progress;
      worker.RunWorkerCompleted += Completed;
      worker.RunWorkerAsync();
   }

   // The only purpose of this mouse button handler is to show that the user
   // interface is responsive while the background tasks are running.
   //
   private static void MouseUp(object sender, MouseEventArgs e)
   {
      outputBlock.Text += "\nMouse clicked.\n";
   }

   private static void DoWork(object sender, DoWorkEventArgs e)
   {
      BackgroundWorker worker = (BackgroundWorker) sender;

      // Divide the "work" into three parts, and queue three tasks to run on
      // threadpool threads. Provide random data for each task.

      Random r = new Random();
      // Keep a list of subtasks and a list of their ManualResetEvent objects.
      System.Collections.Generic.List<Subtask> subtasks = 
                                 new System.Collections.Generic.List<Subtask>();
      System.Collections.Generic.List<WaitHandle> finished = 
                                 new System.Collections.Generic.List<WaitHandle>();

      for(int i = 1; i <= 3; i++)
      {
         Subtask task = new Subtask(i, 3000 + r.Next(4000));
         subtasks.Add(task);
         finished.Add(task.Finished);
         ThreadPool.QueueUserWorkItem(task.DoSubtask);
      }


      // Wait for ANY subtask to complete, and show progress.

      // Create an array of ManualResetEvent wait handles. Each subtask will
      // signal its ManualResetEvent when it is finished.
      WaitHandle[] waitHandles = finished.ToArray();
      int index = WaitHandle.WaitTimeout;

      while (index == WaitHandle.WaitTimeout)
      {
         // Wait for any WaitHandle to be signaled. Use a timeout of 250 milliseconds 
         // to send progress reports. If a timeout occurs, WaitTimeout is returned;
         // if a WaitHandle signals, the array index of the WaitHandle is returned.
         //
         index = WaitHandle.WaitAny(waitHandles, 250);
         worker.ReportProgress(1);
      }


      // In an actual application, the result of the first subtask could be 
      // processed now. Instead, signal the user interface that the first
      // subtask is done.
      worker.ReportProgress(2);


      // Wait for ALL subtasks to complete, and show progress every 1/4 second if
      // the WaitAll times out.

      while (!WaitHandle.WaitAll(waitHandles, 250))
      {
         // If the WaitAll timed out, show progress.
         worker.ReportProgress(3);
      }


      // Generate a report and return it as the result.
      Subtask first = subtasks[index];
      double total = 0.0;

      foreach( Subtask task in subtasks )
      {
         total += task.Result.TotalMilliseconds;
      }

      e.Result = String.Format(
         "Task {0} was the first to complete, with a duration of {1} seconds.\n"
            + "The total duration of all tasks was {2} seconds.\n", 
         first.SubtaskNumber, 
         first.Result.TotalMilliseconds/1000, 
         total/1000);
   }

   private static void Progress(object sender, ProgressChangedEventArgs e)
   {
      if (e.ProgressPercentage == 2)
      {
         outputBlock.Text += "\nFirst subtask is complete.\n";
      }
      else
      {
         outputBlock.Text += ".";
      }
   }

   private static void Completed(object sender, RunWorkerCompletedEventArgs e)
   {
      BackgroundWorker worker = (BackgroundWorker) sender;
      worker.DoWork -= DoWork;
      worker.ProgressChanged -= Progress;
      worker.RunWorkerCompleted -= Completed;

      outputBlock.Text += 
         String.Format("\n{0}\nTo repeat the demo, refresh the page.", e.Result);
   }
}

class Subtask
{
   // Signal this ManualResetEvent when the task is finished.
   internal ManualResetEvent Finished = new ManualResetEvent(false);
   internal int SubtaskNumber;
   internal TimeSpan Result;
   private int data;

   internal Subtask(int number, int data)
   {
      SubtaskNumber = number;
      this.data = data;
   }

   internal void DoSubtask(object state)
   {
      DateTime start = DateTime.Now;
      Thread.Sleep(data);
      // Return a TimeSpan that represents the duration of the task.
      Result = DateTime.Now-start;
      Finished.Set();
   }
}

/* This code produces output similar to the following:

Demo is running. The BackgroundWorker waits for the first subtask to complete,
then waits for all subtasks to complete and produces a report.
Click here at any time to show that the user interface is responsive.
.....
Mouse clicked.
...........
First subtask is complete.
............
Task 3 was the first to complete, with a duration of 3.178 seconds.
The total duration of all tasks was 15.3553943 seconds.

To repeat the demo, refresh the page.
 */


Windows Phone OS

지원되는 버전: 8.0, 7.1, 7.0

Windows Phone

이 형식은 스레드로부터 안전합니다.

Microsoft는 MSDN 웹 사이트에 대한 귀하의 의견을 이해하기 위해 온라인 설문 조사를 진행하고 있습니다. 참여하도록 선택하시면 MSDN 웹 사이트에서 나가실 때 온라인 설문 조사가 표시됩니다.

참여하시겠습니까?
표시:
© 2015 Microsoft