WaitHandle.SignalAndWait 方法

定义

向一个 WaitHandle 发出信号并等待另一个。

重载

SignalAndWait(WaitHandle, WaitHandle)

向一个 WaitHandle 发出信号并等待另一个。

SignalAndWait(WaitHandle, WaitHandle, Int32, Boolean)

向一个 WaitHandle 发出信号并等待另一个,指定超时间隔为 32 位有符号整数,并指定在进入等待前是否退出上下文的同步域。

SignalAndWait(WaitHandle, WaitHandle, TimeSpan, Boolean)

向一个 WaitHandle 发出信号并等待另一个,指定超时间隔为 TimeSpan,并指定在进入等待前是否退出上下文的同步域。

SignalAndWait(WaitHandle, WaitHandle)

Source:
WaitHandle.cs
Source:
WaitHandle.cs
Source:
WaitHandle.cs

向一个 WaitHandle 发出信号并等待另一个。

public:
 static bool SignalAndWait(System::Threading::WaitHandle ^ toSignal, System::Threading::WaitHandle ^ toWaitOn);
public static bool SignalAndWait (System.Threading.WaitHandle toSignal, System.Threading.WaitHandle toWaitOn);
static member SignalAndWait : System.Threading.WaitHandle * System.Threading.WaitHandle -> bool
Public Shared Function SignalAndWait (toSignal As WaitHandle, toWaitOn As WaitHandle) As Boolean

参数

toSignal
WaitHandle

要发出信号的 WaitHandle

toWaitOn
WaitHandle

要等待的 WaitHandle

返回

如果信号和等待都成功完成,则为 true;如果等待没有完成,则此方法不返回。

例外

toSignalnull

toWaitOnnull

在一个处于 STA 状态的线程上调用了该方法。

toSignal 是信号量,已达到最大计数。

等待结束,因为线程在未释放互斥的情况下退出。

示例

下面的代码示例使用 SignalAndWait(WaitHandle, WaitHandle) 方法重载允许main线程向阻塞的线程发出信号,然后等待线程完成任务。

该示例启动五个 EventWaitHandle 线程,允许它们阻止使用 EventResetMode.AutoReset 标志创建的 ,然后在用户每次按 ENTER 键时释放一个线程。 然后,该示例将另外五个 EventWaitHandle 线程排队,并使用使用 EventResetMode.ManualReset 标志创建的 释放它们。

using namespace System;
using namespace System::Threading;

public ref class Example
{
private:
   // The EventWaitHandle used to demonstrate the difference
   // between AutoReset and ManualReset synchronization events.
   //
   static EventWaitHandle^ ewh;

   // A counter to make sure all threads are started and
   // blocked before any are released. A Long is used to show
   // the use of the 64-bit Interlocked methods.
   //
   static __int64 threadCount = 0;

   // An AutoReset event that allows the main thread to block
   // until an exiting thread has decremented the count.
   //
   static EventWaitHandle^ clearCount =
      gcnew EventWaitHandle( false,EventResetMode::AutoReset );

public:
   [MTAThread]
   static void main()
   {
      // Create an AutoReset EventWaitHandle.
      //
      ewh = gcnew EventWaitHandle( false,EventResetMode::AutoReset );
      
      // Create and start five numbered threads. Use the
      // ParameterizedThreadStart delegate, so the thread
      // number can be passed as an argument to the Start
      // method.
      for ( int i = 0; i <= 4; i++ )
      {
         Thread^ t = gcnew Thread(
            gcnew ParameterizedThreadStart( ThreadProc ) );
         t->Start( i );
      }
      
      // Wait until all the threads have started and blocked.
      // When multiple threads use a 64-bit value on a 32-bit
      // system, you must access the value through the
      // Interlocked class to guarantee thread safety.
      //
      while ( Interlocked::Read( threadCount ) < 5 )
      {
         Thread::Sleep( 500 );
      }

      // Release one thread each time the user presses ENTER,
      // until all threads have been released.
      //
      while ( Interlocked::Read( threadCount ) > 0 )
      {
         Console::WriteLine( L"Press ENTER to release a waiting thread." );
         Console::ReadLine();
         
         // SignalAndWait signals the EventWaitHandle, which
         // releases exactly one thread before resetting,
         // because it was created with AutoReset mode.
         // SignalAndWait then blocks on clearCount, to
         // allow the signaled thread to decrement the count
         // before looping again.
         //
         WaitHandle::SignalAndWait( ewh, clearCount );
      }
      Console::WriteLine();
      
      // Create a ManualReset EventWaitHandle.
      //
      ewh = gcnew EventWaitHandle( false,EventResetMode::ManualReset );
      
      // Create and start five more numbered threads.
      //
      for ( int i = 0; i <= 4; i++ )
      {
         Thread^ t = gcnew Thread(
            gcnew ParameterizedThreadStart( ThreadProc ) );
         t->Start( i );
      }
      
      // Wait until all the threads have started and blocked.
      //
      while ( Interlocked::Read( threadCount ) < 5 )
      {
         Thread::Sleep( 500 );
      }

      // Because the EventWaitHandle was created with
      // ManualReset mode, signaling it releases all the
      // waiting threads.
      //
      Console::WriteLine( L"Press ENTER to release the waiting threads." );
      Console::ReadLine();
      ewh->Set();

   }

   static void ThreadProc( Object^ data )
   {
      int index = static_cast<Int32>(data);

      Console::WriteLine( L"Thread {0} blocks.", data );
      // Increment the count of blocked threads.
      Interlocked::Increment( threadCount );
      
      // Wait on the EventWaitHandle.
      ewh->WaitOne();

      Console::WriteLine( L"Thread {0} exits.", data );
      // Decrement the count of blocked threads.
      Interlocked::Decrement( threadCount );
      
      // After signaling ewh, the main thread blocks on
      // clearCount until the signaled thread has
      // decremented the count. Signal it now.
      //
      clearCount->Set();
   }
};
using System;
using System.Threading;

public class Example
{
    // The EventWaitHandle used to demonstrate the difference
    // between AutoReset and ManualReset synchronization events.
    //
    private static EventWaitHandle ewh;

    // A counter to make sure all threads are started and
    // blocked before any are released. A Long is used to show
    // the use of the 64-bit Interlocked methods.
    //
    private static long threadCount = 0;

    // An AutoReset event that allows the main thread to block
    // until an exiting thread has decremented the count.
    //
    private static EventWaitHandle clearCount = 
        new EventWaitHandle(false, EventResetMode.AutoReset);

    [MTAThread]
    public static void Main()
    {
        // Create an AutoReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.AutoReset);

        // Create and start five numbered threads. Use the
        // ParameterizedThreadStart delegate, so the thread
        // number can be passed as an argument to the Start 
        // method.
        for (int i = 0; i <= 4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        // When multiple threads use a 64-bit value on a 32-bit
        // system, you must access the value through the
        // Interlocked class to guarantee thread safety.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Release one thread each time the user presses ENTER,
        // until all threads have been released.
        //
        while (Interlocked.Read(ref threadCount) > 0)
        {
            Console.WriteLine("Press ENTER to release a waiting thread.");
            Console.ReadLine();

            // SignalAndWait signals the EventWaitHandle, which
            // releases exactly one thread before resetting, 
            // because it was created with AutoReset mode. 
            // SignalAndWait then blocks on clearCount, to 
            // allow the signaled thread to decrement the count
            // before looping again.
            //
            WaitHandle.SignalAndWait(ewh, clearCount);
        }
        Console.WriteLine();

        // Create a ManualReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);

        // Create and start five more numbered threads.
        //
        for(int i=0; i<=4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Because the EventWaitHandle was created with
        // ManualReset mode, signaling it releases all the
        // waiting threads.
        //
        Console.WriteLine("Press ENTER to release the waiting threads.");
        Console.ReadLine();
        ewh.Set();
    }

    public static void ThreadProc(object data)
    {
        int index = (int) data;

        Console.WriteLine("Thread {0} blocks.", data);
        // Increment the count of blocked threads.
        Interlocked.Increment(ref threadCount);

        // Wait on the EventWaitHandle.
        ewh.WaitOne();

        Console.WriteLine("Thread {0} exits.", data);
        // Decrement the count of blocked threads.
        Interlocked.Decrement(ref threadCount);

        // After signaling ewh, the main thread blocks on
        // clearCount until the signaled thread has 
        // decremented the count. Signal it now.
        //
        clearCount.Set();
    }
}
Imports System.Threading

Public Class Example

    ' The EventWaitHandle used to demonstrate the difference
    ' between AutoReset and ManualReset synchronization events.
    '
    Private Shared ewh As EventWaitHandle

    ' A counter to make sure all threads are started and
    ' blocked before any are released. A Long is used to show
    ' the use of the 64-bit Interlocked methods.
    '
    Private Shared threadCount As Long = 0

    ' An AutoReset event that allows the main thread to block
    ' until an exiting thread has decremented the count.
    '
    Private Shared clearCount As New EventWaitHandle(False, _
        EventResetMode.AutoReset)

    <MTAThread> _
    Public Shared Sub Main()

        ' Create an AutoReset EventWaitHandle.
        '
        ewh = New EventWaitHandle(False, EventResetMode.AutoReset)

        ' Create and start five numbered threads. Use the
        ' ParameterizedThreadStart delegate, so the thread
        ' number can be passed as an argument to the Start 
        ' method.
        For i As Integer = 0 To 4
            Dim t As New Thread(AddressOf ThreadProc)
            t.Start(i)
        Next i

        ' Wait until all the threads have started and blocked.
        ' When multiple threads use a 64-bit value on a 32-bit
        ' system, you must access the value through the
        ' Interlocked class to guarantee thread safety.
        '
        While Interlocked.Read(threadCount) < 5
            Thread.Sleep(500)
        End While

        ' Release one thread each time the user presses ENTER,
        ' until all threads have been released.
        '
        While Interlocked.Read(threadCount) > 0
            Console.WriteLine("Press ENTER to release a waiting thread.")
            Console.ReadLine()

            ' SignalAndWait signals the EventWaitHandle, which
            ' releases exactly one thread before resetting, 
            ' because it was created with AutoReset mode. 
            ' SignalAndWait then blocks on clearCount, to 
            ' allow the signaled thread to decrement the count
            ' before looping again.
            '
            WaitHandle.SignalAndWait(ewh, clearCount)
        End While
        Console.WriteLine()

        ' Create a ManualReset EventWaitHandle.
        '
        ewh = New EventWaitHandle(False, EventResetMode.ManualReset)

        ' Create and start five more numbered threads.
        '
        For i As Integer = 0 To 4
            Dim t As New Thread(AddressOf ThreadProc)
            t.Start(i)
        Next i

        ' Wait until all the threads have started and blocked.
        '
        While Interlocked.Read(threadCount) < 5
            Thread.Sleep(500)
        End While

        ' Because the EventWaitHandle was created with
        ' ManualReset mode, signaling it releases all the
        ' waiting threads.
        '
        Console.WriteLine("Press ENTER to release the waiting threads.")
        Console.ReadLine()
        ewh.Set()
        
    End Sub

    Public Shared Sub ThreadProc(ByVal data As Object)
        Dim index As Integer = CInt(data)

        Console.WriteLine("Thread {0} blocks.", data)
        ' Increment the count of blocked threads.
        Interlocked.Increment(threadCount)

        ' Wait on the EventWaitHandle.
        ewh.WaitOne()

        Console.WriteLine("Thread {0} exits.", data)
        ' Decrement the count of blocked threads.
        Interlocked.Decrement(threadCount)

        ' After signaling ewh, the main thread blocks on
        ' clearCount until the signaled thread has 
        ' decremented the count. Signal it now.
        '
        clearCount.Set()
    End Sub
End Class

注解

此操作不一定是原子操作。 在当前线程发出信号 toSignal 之后,但在等待 toWaitOn之前,在另一个处理器上运行的线程可能会发出信号 toWaitOn 或等待。

适用于

SignalAndWait(WaitHandle, WaitHandle, Int32, Boolean)

Source:
WaitHandle.cs
Source:
WaitHandle.cs
Source:
WaitHandle.cs

向一个 WaitHandle 发出信号并等待另一个,指定超时间隔为 32 位有符号整数,并指定在进入等待前是否退出上下文的同步域。

public:
 static bool SignalAndWait(System::Threading::WaitHandle ^ toSignal, System::Threading::WaitHandle ^ toWaitOn, int millisecondsTimeout, bool exitContext);
public static bool SignalAndWait (System.Threading.WaitHandle toSignal, System.Threading.WaitHandle toWaitOn, int millisecondsTimeout, bool exitContext);
static member SignalAndWait : System.Threading.WaitHandle * System.Threading.WaitHandle * int * bool -> bool
Public Shared Function SignalAndWait (toSignal As WaitHandle, toWaitOn As WaitHandle, millisecondsTimeout As Integer, exitContext As Boolean) As Boolean

参数

toSignal
WaitHandle

要发出信号的 WaitHandle

toWaitOn
WaitHandle

要等待的 WaitHandle

millisecondsTimeout
Int32

一个整数,表示要等待的间隔。 如果值是 Infinite,即 -1,则等待是无限期的。

exitContext
Boolean

如果等待之前先退出上下文的同步域(如果在同步上下文中),并在稍后重新获取它,则为 true;否则为 false

返回

如果信号发送和等待均成功完成,则为 true;如果信号发送完成,但等待超时,则为 false

例外

toSignalnull

toWaitOnnull

对处于 STA 状态的线程调用了此方法。

无法终止 WaitHandle,因为它将超过其最大计数。

millisecondsTimeout 是一个非 -1 的负数,而 -1 表示无限期超时。

等待结束,因为线程在未释放互斥的情况下退出。

注解

此操作不一定是原子操作。 在当前线程发出信号 toSignal 之后,但在等待 toWaitOn之前,在另一个处理器上运行的线程可能会发出信号 toWaitOn 或等待。

如果 millisecondsTimeout 为零,则该方法不会阻止。 它测试 的状态 toWaitOn 并立即返回。

退出上下文

除非 exitContext 从非默认托管上下文内部调用此方法,否则 参数无效。 如果线程位于对派生自 ContextBoundObject的类实例的调用内,则托管上下文可以是非默认的。 即使当前正在对不是派生自 ContextBoundObject的类(如 ) String执行方法,也可以位于非默认上下文中(如果 ContextBoundObject 位于当前应用程序域中的堆栈上)。

当代码在非默认上下文中执行时,将 指定 trueexitContext 会导致线程退出非默认托管上下文 (即在执行此方法之前转换为默认上下文) 。 对此方法的调用完成后,线程将返回到原始非默认上下文。

当上下文绑定类具有 属性时, SynchronizationAttribute 退出上下文可能很有用。 在这种情况下,将自动同步对 类成员的所有调用,并且同步域是类的整个代码主体。 如果成员的调用堆栈中的代码调用此方法并为 指定 trueexitContext,则线程将退出同步域,从而允许在调用 对象的任何成员时被阻止的线程继续。 此方法返回时,进行调用的线程必须等待重新进入同步域。

适用于

SignalAndWait(WaitHandle, WaitHandle, TimeSpan, Boolean)

Source:
WaitHandle.cs
Source:
WaitHandle.cs
Source:
WaitHandle.cs

向一个 WaitHandle 发出信号并等待另一个,指定超时间隔为 TimeSpan,并指定在进入等待前是否退出上下文的同步域。

public:
 static bool SignalAndWait(System::Threading::WaitHandle ^ toSignal, System::Threading::WaitHandle ^ toWaitOn, TimeSpan timeout, bool exitContext);
public static bool SignalAndWait (System.Threading.WaitHandle toSignal, System.Threading.WaitHandle toWaitOn, TimeSpan timeout, bool exitContext);
static member SignalAndWait : System.Threading.WaitHandle * System.Threading.WaitHandle * TimeSpan * bool -> bool
Public Shared Function SignalAndWait (toSignal As WaitHandle, toWaitOn As WaitHandle, timeout As TimeSpan, exitContext As Boolean) As Boolean

参数

toSignal
WaitHandle

要发出信号的 WaitHandle

toWaitOn
WaitHandle

要等待的 WaitHandle

timeout
TimeSpan

一个 TimeSpan,表示要等待的间隔。 如果值是 -1,则等待是无限期的。

exitContext
Boolean

如果等待之前先退出上下文的同步域(如果在同步上下文中),并在稍后重新获取它,则为 true;否则为 false

返回

如果信号发送和等待均成功完成,则为 true;如果信号发送完成,但等待超时,则为 false

例外

toSignalnull

toWaitOnnull

在一个处于 STA 状态的线程上调用了该方法。

toSignal 是信号量,已达到最大计数。

timeout 计算为 -1 以外的负毫秒数。

- 或 -

timeout 大于 Int32.MaxValue

等待结束,因为线程在未释放互斥的情况下退出。

注解

此操作不一定是原子操作。 在当前线程发出信号 toSignal 之后,但在等待 toWaitOn之前,在另一个处理器上运行的线程可能会发出信号 toWaitOn 或等待。

timeout 最大值为 Int32.MaxValue

如果 timeout 为零,则该方法不会阻止。 它测试 的状态 toWaitOn 并立即返回。

退出上下文

除非 exitContext 从非默认托管上下文内部调用此方法,否则 参数无效。 如果线程位于对派生自 ContextBoundObject的类实例的调用内,则托管上下文可以是非默认的。 即使当前正在对不是派生自 ContextBoundObject的类(如 ) String执行方法,也可以位于非默认上下文中(如果 ContextBoundObject 位于当前应用程序域中的堆栈上)。

当代码在非默认上下文中执行时,将 指定 trueexitContext 会导致线程退出非默认托管上下文 (即在执行此方法之前转换为默认上下文) 。 对此方法的调用完成后,线程将返回到原始非默认上下文。

当上下文绑定类具有 属性时, SynchronizationAttribute 退出上下文可能很有用。 在这种情况下,将自动同步对 类成员的所有调用,并且同步域是类的整个代码主体。 如果成员的调用堆栈中的代码调用此方法并为 指定 trueexitContext,则线程将退出同步域,从而允许在调用 对象的任何成员时被阻止的线程继续。 此方法返回时,进行调用的线程必须等待重新进入同步域。

适用于