Поделиться через


WaitHandle.WaitOne Метод

Определение

Блокирует текущий поток до получения сигнала объектом WaitHandle.

Перегрузки

WaitOne()

Блокирует текущий поток до получения сигнала объектом WaitHandle.

WaitOne(Int32)

Блокирует текущий поток до получения текущим дескриптором WaitHandle сигнала, используя 32-разрядное целое число со знаком для указания интервала времени в миллисекундах.

WaitOne(TimeSpan)

Блокирует текущий поток до получения сигнала текущим экземпляром, используя значение типа TimeSpan для указания интервала времени.

WaitOne(Int32, Boolean)

Блокирует текущий поток до получения сигнала текущим объектом WaitHandle, используя 32-разрядное целое число со знаком для задания периода времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

WaitOne(TimeSpan, Boolean)

Блокирует текущий поток до получения сигнала текущим экземпляром, используя значение типа TimeSpan для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

WaitOne()

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Блокирует текущий поток до получения сигнала объектом WaitHandle.

public:
 virtual bool WaitOne();
public virtual bool WaitOne ();
abstract member WaitOne : unit -> bool
override this.WaitOne : unit -> bool
Public Overridable Function WaitOne () As Boolean

Возвращаемое значение

Значение true, если текущий экземпляр получает сигнал. Пока текущий экземпляр не сигнализирует, метод WaitOne() не возвращает управление.

Исключения

Текущий экземпляр уже удален.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

Текущий экземпляр является прозрачным прокси для объекта WaitHandle в другом домене приложения.

Примеры

В следующем примере кода показано, как использовать дескриптор ожидания, чтобы не допустить завершения процесса, пока он ожидает завершения выполнения фонового потока.

using namespace System;
using namespace System::Threading;
ref class WaitOne
{
private:
   WaitOne(){}


public:
   static void WorkMethod( Object^ stateInfo )
   {
      Console::WriteLine( "Work starting." );
      
      // Simulate time spent working.
      Thread::Sleep( (gcnew Random)->Next( 100, 2000 ) );
      
      // Signal that work is finished.
      Console::WriteLine( "Work ending." );
      dynamic_cast<AutoResetEvent^>(stateInfo)->Set();
   }

};

int main()
{
   Console::WriteLine( "Main starting." );
   AutoResetEvent^ autoEvent = gcnew AutoResetEvent( false );
   ThreadPool::QueueUserWorkItem( gcnew WaitCallback( &WaitOne::WorkMethod ), autoEvent );
   
   // Wait for work method to signal.
   autoEvent->WaitOne(  );
   Console::WriteLine( "Work method signaled.\nMain ending." );
}
using System;
using System.Threading;

class WaitOne
{
    static AutoResetEvent autoEvent = new AutoResetEvent(false);

    static void Main()
    {
        Console.WriteLine("Main starting.");

        ThreadPool.QueueUserWorkItem(
            new WaitCallback(WorkMethod), autoEvent);

        // Wait for work method to signal.
        autoEvent.WaitOne();
        Console.WriteLine("Work method signaled.\nMain ending.");
    }

    static void WorkMethod(object stateInfo) 
    {
        Console.WriteLine("Work starting.");

        // Simulate time spent working.
        Thread.Sleep(new Random().Next(100, 2000));

        // Signal that work is finished.
        Console.WriteLine("Work ending.");
        ((AutoResetEvent)stateInfo).Set();
    }
}
Imports System.Threading

Public Class WaitOne

    Shared autoEvent As New AutoResetEvent(False)

    <MTAThread> _
    Shared Sub Main()
        Console.WriteLine("Main starting.")

        ThreadPool.QueueUserWorkItem(AddressOf WorkMethod, autoEvent)

        ' Wait for work method to signal.
        autoEvent.WaitOne()
        Console.WriteLine("Work method signaled.")
        Console.WriteLine("Main ending.")
    End Sub

    Shared Sub WorkMethod(stateInfo As Object) 
        Console.WriteLine("Work starting.")

        ' Simulate time spent working.
        Thread.Sleep(New Random().Next(100, 2000))

        ' Signal that work is finished.
        Console.WriteLine("Work ending.")
        CType(stateInfo, AutoResetEvent).Set()
    End Sub

End Class

Комментарии

AbandonedMutexExceptionявляется новым в платформа .NET Framework версии 2.0. В предыдущих версиях метод возвращает значение true при WaitOne отказе от мьютекса. Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае мьютекса всей системы это может указывать на то, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

Вызывающий объект этого метода блокируется на неопределенный срок, пока текущий экземпляр не получит сигнал. Используйте этот метод для блокировки до тех пор, пока WaitHandle не получит сигнал из другого потока, например при завершении асинхронной операции. Дополнительные сведения см. в описании интерфейса IAsyncResult.

Вызов перегрузки этого метода эквивалентен вызову перегрузки WaitOne(Int32, Boolean) метода и указанию -1 или Timeout.Infinite для первого параметра и false для второго параметра.

Переопределите этот метод, чтобы настроить поведение производных классов.

Применяется к

WaitOne(Int32)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Блокирует текущий поток до получения текущим дескриптором WaitHandle сигнала, используя 32-разрядное целое число со знаком для указания интервала времени в миллисекундах.

public:
 virtual bool WaitOne(int millisecondsTimeout);
public virtual bool WaitOne (int millisecondsTimeout);
abstract member WaitOne : int -> bool
override this.WaitOne : int -> bool
Public Overridable Function WaitOne (millisecondsTimeout As Integer) As Boolean

Параметры

millisecondsTimeout
Int32

Время ожидания в миллисекундах или функция Infinite (-1) в случае неограниченного времени ожидания.

Возвращаемое значение

Значение true при получении сигнала текущим экземпляром; в противном случае — значение false.

Исключения

Текущий экземпляр уже удален.

Параметр millisecondsTimeout является отрицательным числом, отличным от –1, что означает бесконечное время ожидания.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

Текущий экземпляр является прозрачным прокси для объекта WaitHandle в другом домене приложения.

Примеры

В следующем примере кода показано, как использовать дескриптор ожидания, чтобы не допустить завершения процесса, пока он ожидает завершения выполнения фонового потока.

using namespace System;
using namespace System::Threading;
ref class WaitOne
{
private:
   WaitOne(){}


public:
   static void WorkMethod( Object^ stateInfo )
   {
      Console::WriteLine( "Work starting." );
      
      // Simulate time spent working.
      Thread::Sleep( (gcnew Random)->Next( 100, 2000 ) );
      
      // Signal that work is finished.
      Console::WriteLine( "Work ending." );
      dynamic_cast<AutoResetEvent^>(stateInfo)->Set();
   }

};

int main()
{
   Console::WriteLine( "Main starting." );
   AutoResetEvent^ autoEvent = gcnew AutoResetEvent( false );
   ThreadPool::QueueUserWorkItem( gcnew WaitCallback( &WaitOne::WorkMethod ), autoEvent );
   
   // Wait for work method to signal.
   if ( autoEvent->WaitOne( 1000 ) )
   {
      Console::WriteLine( "Work method signaled." );
   }
   else
   {
      Console::WriteLine( "Timed out waiting for work "
      "method to signal." );
   }

   Console::WriteLine( "Main ending." );
}
using System;
using System.Threading;

class WaitOne
{
    static AutoResetEvent autoEvent = new AutoResetEvent(false);

    static void Main()
    {
        Console.WriteLine("Main starting.");

        ThreadPool.QueueUserWorkItem(
            new WaitCallback(WorkMethod), autoEvent);

        // Wait for work method to signal.
        if(autoEvent.WaitOne(1000))
        {
            Console.WriteLine("Work method signaled.");
        }
        else
        {
            Console.WriteLine("Timed out waiting for work " +
                "method to signal.");
        }
        Console.WriteLine("Main ending.");
    }

    static void WorkMethod(object stateInfo) 
    {
        Console.WriteLine("Work starting.");

        // Simulate time spent working.
        Thread.Sleep(new Random().Next(100, 2000));

        // Signal that work is finished.
        Console.WriteLine("Work ending.");
        ((AutoResetEvent)stateInfo).Set();
    }
}
Imports System.Threading

Public Class WaitOne

    Shared autoEvent As New AutoResetEvent(False)

    <MTAThread> _
    Shared Sub Main()
        Console.WriteLine("Main starting.")

        ThreadPool.QueueUserWorkItem(AddressOf WorkMethod, autoEvent)

        ' Wait for work method to signal.
        If autoEvent.WaitOne(1000) Then
            Console.WriteLine("Work method signaled.")
        Else
            Console.WriteLine("Timed out waiting for work " & _
                "method to signal.")
        End If

        Console.WriteLine("Main ending.")
    End Sub

    Shared Sub WorkMethod(stateInfo As Object) 
        Console.WriteLine("Work starting.")

        ' Simulate time spent working.
        Thread.Sleep(New Random().Next(100, 2000))

        ' Signal that work is finished.
        Console.WriteLine("Work ending.")
        CType(stateInfo, AutoResetEvent).Set()
    End Sub

End Class

Комментарии

Если millisecondsTimeout равно нулю, метод не блокирует. Он проверяет состояние дескриптора ожидания и возвращает немедленно.

Вызывающий объект этого метода блокируется до тех пор, пока текущий экземпляр не получит сигнал или не наступает время ожидания. Используйте этот метод для блокировки до тех пор, пока WaitHandle не получит сигнал из другого потока, например при завершении асинхронной операции. Дополнительные сведения см. в описании интерфейса IAsyncResult.

Переопределите этот метод, чтобы настроить поведение производных классов.

Вызов перегрузки этого метода совпадает с вызовом перегрузки WaitOne(Int32, Boolean) и указанием false для exitContext.

Применяется к

WaitOne(TimeSpan)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Блокирует текущий поток до получения сигнала текущим экземпляром, используя значение типа TimeSpan для указания интервала времени.

public:
 virtual bool WaitOne(TimeSpan timeout);
public virtual bool WaitOne (TimeSpan timeout);
abstract member WaitOne : TimeSpan -> bool
override this.WaitOne : TimeSpan -> bool
Public Overridable Function WaitOne (timeout As TimeSpan) As Boolean

Параметры

timeout
TimeSpan

Период TimeSpan, представляющий время ожидания в миллисекундах, или период TimeSpan, представляющий -1 миллисекунду для неограниченного ожидания.

Возвращаемое значение

Значение true при получении сигнала текущим экземпляром; в противном случае — значение false.

Исключения

Текущий экземпляр уже удален.

timeout является отрицательным числом, отличным от -1 миллисекунды, которое представляет неограниченное время ожидания.

-или-

timeout больше , чем Int32.MaxValue.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

Текущий экземпляр является прозрачным прокси для объекта WaitHandle в другом домене приложения.

Комментарии

Если timeout равно нулю, метод не блокирует. Он проверяет состояние дескриптора ожидания и возвращает немедленно.

Вызывающий объект этого метода блокируется до тех пор, пока текущий экземпляр не получит сигнал или не наступает время ожидания. Используйте этот метод для блокировки до тех пор, пока WaitHandle не получит сигнал из другого потока, например при завершении асинхронной операции. Дополнительные сведения см. в описании интерфейса IAsyncResult.

Переопределите этот метод, чтобы настроить поведение производных классов.

Максимальное значение для timeoutInt32.MaxValue.

Вызов перегрузки этого метода совпадает с вызовом перегрузки WaitOne(TimeSpan, Boolean) и указанием false для exitContext.

Применяется к

WaitOne(Int32, Boolean)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Блокирует текущий поток до получения сигнала текущим объектом WaitHandle, используя 32-разрядное целое число со знаком для задания периода времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

public:
 virtual bool WaitOne(int millisecondsTimeout, bool exitContext);
public virtual bool WaitOne (int millisecondsTimeout, bool exitContext);
abstract member WaitOne : int * bool -> bool
override this.WaitOne : int * bool -> bool
Public Overridable Function WaitOne (millisecondsTimeout As Integer, exitContext As Boolean) As Boolean

Параметры

millisecondsTimeout
Int32

Время ожидания в миллисекундах или функция Infinite (-1) в случае неограниченного времени ожидания.

exitContext
Boolean

Значение true для выхода из домена синхронизации в текущем контексте перед ожиданием (в синхронизированном контексте) с его последующим повторным получением; в противном случае — false.

Возвращаемое значение

Значение true при получении сигнала текущим экземпляром; в противном случае — значение false.

Исключения

Текущий экземпляр уже удален.

Параметр millisecondsTimeout является отрицательным числом, отличным от –1, что означает бесконечное время ожидания.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

Текущий экземпляр является прозрачным прокси для объекта WaitHandle в другом домене приложения.

Примеры

В следующем примере показано поведение перегрузки WaitOne(Int32, Boolean) метода при вызове в домене синхронизации. Во-первых, поток ожидает с exitContext заданным значением false и блокирует время ожидания, пока не истечет время ожидания. Второй поток выполняется после завершения первого потока и ожидает с exitContext параметром true. Вызов сигнала дескриптора ожидания для этого второго потока не блокируется, и поток завершается до истечения времени ожидания.

using namespace System;
using namespace System::Threading;
using namespace System::Runtime::Remoting::Contexts;

[Synchronization(true)]
public ref class SyncingClass : ContextBoundObject
{
private:
    EventWaitHandle^ waitHandle;

public:
    SyncingClass()
    {
         waitHandle =
            gcnew EventWaitHandle(false, EventResetMode::ManualReset);
    }

    void Signal()
    {
        Console::WriteLine("Thread[{0:d4}]: Signalling...", Thread::CurrentThread->GetHashCode());
        waitHandle->Set();
    }

    void DoWait(bool leaveContext)
    {
        bool signalled;

        waitHandle->Reset();
        Console::WriteLine("Thread[{0:d4}]: Waiting...", Thread::CurrentThread->GetHashCode());
        signalled = waitHandle->WaitOne(3000, leaveContext);
        if (signalled)
        {
            Console::WriteLine("Thread[{0:d4}]: Wait released!!!", Thread::CurrentThread->GetHashCode());
        }
        else
        {
            Console::WriteLine("Thread[{0:d4}]: Wait timeout!!!", Thread::CurrentThread->GetHashCode());
        }
    }
};

public ref class TestSyncDomainWait
{
public:
    static void Main()
    {
        SyncingClass^ syncClass = gcnew SyncingClass();

        Thread^ runWaiter;

        Console::WriteLine("\nWait and signal INSIDE synchronization domain:\n");
        runWaiter = gcnew Thread(gcnew ParameterizedThreadStart(&TestSyncDomainWait::RunWaitKeepContext));
        runWaiter->Start(syncClass);
        Thread::Sleep(1000);
        Console::WriteLine("Thread[{0:d4}]: Signal...", Thread::CurrentThread->GetHashCode());
        // This call to Signal will block until the timeout in DoWait expires.
        syncClass->Signal();
        runWaiter->Join();

        Console::WriteLine("\nWait and signal OUTSIDE synchronization domain:\n");
        runWaiter = gcnew Thread(gcnew ParameterizedThreadStart(&TestSyncDomainWait::RunWaitLeaveContext));
        runWaiter->Start(syncClass);
        Thread::Sleep(1000);
        Console::WriteLine("Thread[{0:d4}]: Signal...", Thread::CurrentThread->GetHashCode());
        // This call to Signal is unblocked and will set the wait handle to
        // release the waiting thread.
        syncClass->Signal();
        runWaiter->Join();
    }

    static void RunWaitKeepContext(Object^ parm)
    {
        ((SyncingClass^)parm)->DoWait(false);
    }

    static void RunWaitLeaveContext(Object^ parm)
    {
        ((SyncingClass^)parm)->DoWait(true);
    }
};

int main()
{
    TestSyncDomainWait::Main();
}
// The output for the example program will be similar to the following:
//
// Wait and signal INSIDE synchronization domain:
//
// Thread[0004]: Waiting...
// Thread[0001]: Signal...
// Thread[0004]: Wait timeout!!!
// Thread[0001]: Signalling...
//
// Wait and signal OUTSIDE synchronization domain:
//
// Thread[0006]: Waiting...
// Thread[0001]: Signal...
// Thread[0001]: Signalling...
// Thread[0006]: Wait released!!!
using System;
using System.Threading;
using System.Runtime.Remoting.Contexts;

[Synchronization(true)]
public class SyncingClass : ContextBoundObject
{
    private EventWaitHandle waitHandle;

    public SyncingClass()
    {
         waitHandle =
            new EventWaitHandle(false, EventResetMode.ManualReset);
    }

    public void Signal()
    {
        Console.WriteLine("Thread[{0:d4}]: Signalling...", Thread.CurrentThread.GetHashCode());
        waitHandle.Set();
    }

    public void DoWait(bool leaveContext)
    {
        bool signalled;

        waitHandle.Reset();
        Console.WriteLine("Thread[{0:d4}]: Waiting...", Thread.CurrentThread.GetHashCode());
        signalled = waitHandle.WaitOne(3000, leaveContext);
        if (signalled)
        {
            Console.WriteLine("Thread[{0:d4}]: Wait released!!!", Thread.CurrentThread.GetHashCode());
        }
        else
        {
            Console.WriteLine("Thread[{0:d4}]: Wait timeout!!!", Thread.CurrentThread.GetHashCode());
        }
    }
}

public class TestSyncDomainWait
{
    public static void Main()
    {
        SyncingClass syncClass = new SyncingClass();

        Thread runWaiter;

        Console.WriteLine("\nWait and signal INSIDE synchronization domain:\n");
        runWaiter = new Thread(RunWaitKeepContext);
        runWaiter.Start(syncClass);
        Thread.Sleep(1000);
        Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode());
        // This call to Signal will block until the timeout in DoWait expires.
        syncClass.Signal();
        runWaiter.Join();

        Console.WriteLine("\nWait and signal OUTSIDE synchronization domain:\n");
        runWaiter = new Thread(RunWaitLeaveContext);
        runWaiter.Start(syncClass);
        Thread.Sleep(1000);
        Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode());
        // This call to Signal is unblocked and will set the wait handle to
        // release the waiting thread.
        syncClass.Signal();
        runWaiter.Join();
    }

    public static void RunWaitKeepContext(object parm)
    {
        ((SyncingClass)parm).DoWait(false);
    }

    public static void RunWaitLeaveContext(object parm)
    {
        ((SyncingClass)parm).DoWait(true);
    }
}

// The output for the example program will be similar to the following:
//
// Wait and signal INSIDE synchronization domain:
//
// Thread[0004]: Waiting...
// Thread[0001]: Signal...
// Thread[0004]: Wait timeout!!!
// Thread[0001]: Signalling...
//
// Wait and signal OUTSIDE synchronization domain:
//
// Thread[0006]: Waiting...
// Thread[0001]: Signal...
// Thread[0001]: Signalling...
// Thread[0006]: Wait released!!!
Imports System.Threading
Imports System.Runtime.Remoting.Contexts

<Synchronization(true)>
Public Class SyncingClass
    Inherits ContextBoundObject
    
    Private waitHandle As EventWaitHandle

    Public Sub New()
         waitHandle = New EventWaitHandle(false, EventResetMode.ManualReset)
    End Sub

    Public Sub Signal()
        Console.WriteLine("Thread[{0:d4}]: Signalling...", Thread.CurrentThread.GetHashCode())
        waitHandle.Set()
    End Sub

    Public Sub DoWait(leaveContext As Boolean)
        Dim signalled As Boolean

        waitHandle.Reset()
        Console.WriteLine("Thread[{0:d4}]: Waiting...", Thread.CurrentThread.GetHashCode())
        signalled = waitHandle.WaitOne(3000, leaveContext)
        If signalled Then
            Console.WriteLine("Thread[{0:d4}]: Wait released!!!", Thread.CurrentThread.GetHashCode())
        Else
            Console.WriteLine("Thread[{0:d4}]: Wait timeout!!!", Thread.CurrentThread.GetHashCode())
        End If
    End Sub
End Class

Public Class TestSyncDomainWait
    Public Shared Sub Main()
        Dim syncClass As New SyncingClass()

        Dim runWaiter As Thread

        Console.WriteLine(Environment.NewLine + "Wait and signal INSIDE synchronization domain:" + Environment.NewLine)
        runWaiter = New Thread(AddressOf RunWaitKeepContext)
        runWaiter.Start(syncClass)
        Thread.Sleep(1000)
        Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode())
        ' This call to Signal will block until the timeout in DoWait expires.
        syncClass.Signal()
        runWaiter.Join()

        Console.WriteLine(Environment.NewLine + "Wait and signal OUTSIDE synchronization domain:" + Environment.NewLine)
        runWaiter = New Thread(AddressOf RunWaitLeaveContext)
        runWaiter.Start(syncClass)
        Thread.Sleep(1000)
        Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode())
        ' This call to Signal is unblocked and will set the wait handle to
        ' release the waiting thread.
        syncClass.Signal()
        runWaiter.Join()
    End Sub

    Public Shared Sub RunWaitKeepContext(parm As Object)
        Dim syncClass As SyncingClass = CType(parm, SyncingClass)
        syncClass.DoWait(False)
    End Sub

    Public Shared Sub RunWaitLeaveContext(parm As Object)
        Dim syncClass As SyncingClass = CType(parm, SyncingClass)
        syncClass.DoWait(True)
    End Sub
End Class

' The output for the example program will be similar to the following:
'
' Wait and signal INSIDE synchronization domain:
'
' Thread[0004]: Waiting...
' Thread[0001]: Signal...
' Thread[0004]: Wait timeout!!!
' Thread[0001]: Signalling...
'
' Wait and signal OUTSIDE synchronization domain:
'
' Thread[0006]: Waiting...
' Thread[0001]: Signal...
' Thread[0001]: Signalling...
' Thread[0006]: Wait released!!!

Комментарии

Если millisecondsTimeout равно нулю, метод не блокирует. Он проверяет состояние дескриптора ожидания и возвращает немедленно.

При отказе от мьютекса AbandonedMutexException создается исключение . Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае мьютекса всей системы это может указывать на то, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

Вызывающий объект этого метода блокируется до тех пор, пока текущий экземпляр не получит сигнал или не наступает время ожидания. Используйте этот метод для блокировки до тех пор, пока WaitHandle не получит сигнал из другого потока, например при завершении асинхронной операции. Дополнительные сведения см. в описании интерфейса IAsyncResult.

Переопределите этот метод, чтобы настроить поведение производных классов.

Выход из контекста

Параметр exitContext не действует, если этот метод не вызывается из неразрешимого управляемого контекста. Управляемый контекст может быть неразрешен, если поток находится в вызове экземпляра класса, производного от ContextBoundObject. Даже если в данный момент вы выполняете метод в классе, который не является производным от , например String, вы можете находиться в контексте, отличном от ContextBoundObjectтекущего домена приложения, если ContextBoundObject объект находится в стеке в текущем домене приложения.

Если код выполняется в контексте, отличном от параметров, указание true параметра приводит exitContext к выходу потока из неотделенного управляемого контекста (т. е. для перехода в контекст по умолчанию) перед выполнением этого метода. После завершения вызова этого метода поток возвращается в исходный контекст, отличный от текущего.

Выход из контекста может быть полезен, если у класса, связанного с контекстом SynchronizationAttribute , есть атрибут . В этом случае все вызовы членов класса синхронизируются автоматически, а доменом синхронизации является весь текст кода для класса. Если код в стеке вызовов true элемента вызывает этот метод и указывает для exitContext, поток выходит из домена синхронизации, что позволяет потоку, заблокированном при вызове любого члена объекта, продолжить работу. При возврате этим методом поток, который сделал вызов, должен дождаться повторного ввести домен синхронизации.

Применяется к

WaitOne(TimeSpan, Boolean)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Блокирует текущий поток до получения сигнала текущим экземпляром, используя значение типа TimeSpan для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

public:
 virtual bool WaitOne(TimeSpan timeout, bool exitContext);
public virtual bool WaitOne (TimeSpan timeout, bool exitContext);
abstract member WaitOne : TimeSpan * bool -> bool
override this.WaitOne : TimeSpan * bool -> bool
Public Overridable Function WaitOne (timeout As TimeSpan, exitContext As Boolean) As Boolean

Параметры

timeout
TimeSpan

Период TimeSpan, представляющий время ожидания в миллисекундах, или период TimeSpan, представляющий -1 миллисекунду для неограниченного ожидания.

exitContext
Boolean

Значение true для выхода из домена синхронизации в текущем контексте перед ожиданием (в синхронизированном контексте) с его последующим повторным получением; в противном случае — false.

Возвращаемое значение

Значение true при получении сигнала текущим экземпляром; в противном случае — значение false.

Исключения

Текущий экземпляр уже удален.

timeout является отрицательным числом, отличным от -1 миллисекунды, которое представляет неограниченное время ожидания.

-или-

timeout больше , чем Int32.MaxValue.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

Текущий экземпляр является прозрачным прокси для объекта WaitHandle в другом домене приложения.

Примеры

В следующем примере кода показано, как использовать дескриптор ожидания, чтобы не допустить завершения процесса, пока он ожидает завершения выполнения фонового потока.

using namespace System;
using namespace System::Threading;
ref class WaitOne
{
private:
   WaitOne(){}


public:
   static void WorkMethod( Object^ stateInfo )
   {
      Console::WriteLine( "Work starting." );
      
      // Simulate time spent working.
      Thread::Sleep( (gcnew Random)->Next( 100, 2000 ) );
      
      // Signal that work is finished.
      Console::WriteLine( "Work ending." );
      dynamic_cast<AutoResetEvent^>(stateInfo)->Set();
   }

};

int main()
{
   Console::WriteLine( "Main starting." );
   AutoResetEvent^ autoEvent = gcnew AutoResetEvent( false );
   ThreadPool::QueueUserWorkItem( gcnew WaitCallback( &WaitOne::WorkMethod ), autoEvent );
   
   // Wait for work method to signal.
   if ( autoEvent->WaitOne( TimeSpan(0,0,1), false ) )
   {
      Console::WriteLine( "Work method signaled." );
   }
   else
   {
      Console::WriteLine( "Timed out waiting for work "
      "method to signal." );
   }

   Console::WriteLine( "Main ending." );
}
using System;
using System.Threading;

class WaitOne
{
    static AutoResetEvent autoEvent = new AutoResetEvent(false);

    static void Main()
    {
        Console.WriteLine("Main starting.");

        ThreadPool.QueueUserWorkItem(
            new WaitCallback(WorkMethod), autoEvent);

        // Wait for work method to signal.
        if(autoEvent.WaitOne(new TimeSpan(0, 0, 1), false))
        {
            Console.WriteLine("Work method signaled.");
        }
        else
        {
            Console.WriteLine("Timed out waiting for work " +
                "method to signal.");
        }
        Console.WriteLine("Main ending.");
    }

    static void WorkMethod(object stateInfo) 
    {
        Console.WriteLine("Work starting.");

        // Simulate time spent working.
        Thread.Sleep(new Random().Next(100, 2000));

        // Signal that work is finished.
        Console.WriteLine("Work ending.");
        ((AutoResetEvent)stateInfo).Set();
    }
}
Imports System.Threading

Public Class WaitOne

    Shared autoEvent As New AutoResetEvent(False)

    <MTAThread> _
    Shared Sub Main()
        Console.WriteLine("Main starting.")

        ThreadPool.QueueUserWorkItem(AddressOf WorkMethod, autoEvent)

        ' Wait for work method to signal.
        If autoEvent.WaitOne(New TimeSpan(0, 0, 1), False) Then
            Console.WriteLine("Work method signaled.")
        Else
            Console.WriteLine("Timed out waiting for work " & _
                "method to signal.")
        End If

        Console.WriteLine("Main ending.")
    End Sub

    Shared Sub WorkMethod(stateInfo As Object) 
        Console.WriteLine("Work starting.")

        ' Simulate time spent working.
        Thread.Sleep(New Random().Next(100, 2000))

        ' Signal that work is finished.
        Console.WriteLine("Work ending.")
        CType(stateInfo, AutoResetEvent).Set()
    End Sub

End Class

Комментарии

Если timeout равно нулю, метод не блокируется. Он проверяет состояние дескриптора ожидания и немедленно возвращается.

При отказе от мьютекса AbandonedMutexException создается исключение . Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае системного мьютекса это может означать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

Вызывающий объект этого метода блокируется до тех пор, пока текущий экземпляр не получит сигнал или не наступает время ожидания. Используйте этот метод для блокировки до тех пор, пока не WaitHandle получит сигнал из другого потока, например при завершении асинхронной операции. Дополнительные сведения см. в описании интерфейса IAsyncResult.

Переопределите этот метод, чтобы настроить поведение производных классов.

Максимальное значение для timeoutInt32.MaxValue.

Выход из контекста

Параметр exitContext не действует, если этот метод не вызывается из нестандартного управляемого контекста. Управляемый контекст может быть неразрешен, если поток находится внутри вызова экземпляра класса, производного от ContextBoundObject. Даже если вы в настоящее время выполняете метод в классе, который не является производным от ContextBoundObject, например String, вы можете находиться в контексте, не являющемся стандартным, если ContextBoundObject находится в стеке в текущем домене приложения.

При выполнении кода в контексте, не являющегося стандартным, указание true для exitContext приводит к тому, что перед выполнением этого метода поток выйдет из нестандартного управляемого контекста (т. е. для перехода в контекст по умолчанию). Поток возвращается в исходный контекст nondefault после завершения вызова этого метода.

Выход из контекста может быть полезен, если связанный с контекстом класс имеет SynchronizationAttribute атрибут . В этом случае все вызовы членов класса синхронизируются автоматически, а домен синхронизации — это весь текст кода для класса. Если код в стеке вызовов true члена вызывает этот метод и указывает для exitContext, поток выходит из домена синхронизации, что позволяет потоку, заблокированном при вызове любого члена объекта, продолжить работу. При возврате этого метода поток, который сделал вызов, должен дождаться повторного ввести домен синхронизации.

Применяется к