Windows Dev Center

WaitHandle.WaitAll Method (WaitHandle[])

Waits for all the elements in the specified array to receive a signal.

Namespace:  System.Threading
Assembly:  mscorlib (in mscorlib.dll)

public static bool WaitAll(
	WaitHandle[] waitHandles
)

Parameters

waitHandles
Type: System.Threading.WaitHandle []
An array that contains the objects for which the current instance will wait. This array cannot contain multiple references to the same object.

Return Value

Type: System.Boolean
true when every element in waitHandles has received a signal; otherwise, the method never returns.

ExceptionCondition
ArgumentNullException

The waitHandles parameter is null.

-or-

One or more of the objects in the waitHandles array are null.

ArgumentException

The waitHandles array contains elements that are duplicates.

-or-

waitHandles is an array with no elements.

NotSupportedException

The number of objects in waitHandles is greater than the system permits.

The WaitAll method returns when all the handles are signaled. On some implementations, if more than 64 handles are passed, a NotSupportedException is thrown. If the array contains duplicates, the call fails with an ArgumentException.

Calling this method overload is equivalent to calling the WaitAll(WaitHandle[], Int32) method overload and specifying -1 (or Timeout.Infinite) for millisecondsTimeout.

If you call this method from a single-threaded apartment, and waitHandles contains more than one wait handle, the method deadlocks.

Version Notes

Windows Phone

 WaitAll is present but not supported in Windows Phone.

The following example shows how to divide work among three thread pool threads, and how to use the static WaitAll and WaitAny methods to wait until the subtasks are finished.

The example creates a BackgroundWorker that reports completion to the user interface. By using a BackgroundWorker, the example insulates the user interface thread from the effects of the WaitAny and WaitAll methods, and thus allows the user interface to remain responsive.

The BackgroundWorker runs a DoWork method that creates three tasks by using the ThreadPool.QueueUserWorkItem method, and assigns each task a random amount of work. The example defines a Subtask class to hold the data and thread procedure for each task. Each task has a ManualResetEvent, which it signals when its work is complete.

After starting the tasks, the DoWork method uses the WaitAny(WaitHandle[]) method overload to wait for the shortest subtask to finish. The BackgroundWorker then uses the WaitAll(WaitHandle[]) method overload to wait until the rest of the tasks are complete. The DoWork method then produces a report using the results from all three tasks.

NoteNote:

The shortest task is not necessarily the first to complete. The thread pool threads may not all start immediately and may not be treated equally by the scheduler.

After you start the example, it changes the mouse button event to show user clicks, demonstrating that the user interface remains responsive during the execution of the background tasks.


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.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 += "Mouse 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.

      // 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;

      index = WaitHandle.WaitAny(waitHandles);

      // In an actual application, the result of the first subtask could be 
      // processed now. 


      // Wait for ALL subtasks to complete.      
      WaitHandle.WaitAll(waitHandles);


      // 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 Completed(object sender, RunWorkerCompletedEventArgs e)
   {
      BackgroundWorker worker = (BackgroundWorker) sender;
      worker.DoWork -= DoWork;
      worker.RunWorkerCompleted -= Completed;

      outputBlock.Text += 
         String.Format("{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.
Mouse clicked.
Task 1 was the first to complete, with a duration of 3.3363568 seconds.
The total duration of all tasks was 12.317826 seconds.

To repeat the demo, refresh the page.
 */


Windows Phone OS

Supported in: 8.1, 8.0, 7.1, 7.0

Windows Phone

Show:
© 2015 Microsoft