ManualResetEventSlim 클래스
정의
중요
일부 정보는 릴리스되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.
신호를 받을 때 수동으로 재설정되어야 하는 스레드 동기화 이벤트를 나타냅니다. 이 클래스는 ManualResetEvent의 간단한 대체 항목입니다.
public ref class ManualResetEventSlim : IDisposable
public class ManualResetEventSlim : IDisposable
[System.Runtime.InteropServices.ComVisible(false)]
public class ManualResetEventSlim : IDisposable
type ManualResetEventSlim = class
interface IDisposable
[<System.Runtime.InteropServices.ComVisible(false)>]
type ManualResetEventSlim = class
interface IDisposable
Public Class ManualResetEventSlim
Implements IDisposable
- 상속
-
ManualResetEventSlim
- 특성
- 구현
예제
다음 예제에서는 ManualResetEventSlim.
using System;
using System.Threading;
using System.Threading.Tasks;
class MRESDemo
{
static void Main()
{
MRES_SetWaitReset();
MRES_SpinCountWaitHandle();
}
// Demonstrates:
// ManualResetEventSlim construction
// ManualResetEventSlim.Wait()
// ManualResetEventSlim.Set()
// ManualResetEventSlim.Reset()
// ManualResetEventSlim.IsSet
static void MRES_SetWaitReset()
{
ManualResetEventSlim mres1 = new ManualResetEventSlim(false); // initialize as unsignaled
ManualResetEventSlim mres2 = new ManualResetEventSlim(false); // initialize as unsignaled
ManualResetEventSlim mres3 = new ManualResetEventSlim(true); // initialize as signaled
// Start an asynchronous Task that manipulates mres3 and mres2
var observer = Task.Factory.StartNew(() =>
{
mres1.Wait();
Console.WriteLine("observer sees signaled mres1!");
Console.WriteLine("observer resetting mres3...");
mres3.Reset(); // should switch to unsignaled
Console.WriteLine("observer signalling mres2");
mres2.Set();
});
Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet);
Console.WriteLine("main thread signalling mres1");
mres1.Set(); // This will "kick off" the observer Task
mres2.Wait(); // This won't return until observer Task has finished resetting mres3
Console.WriteLine("main thread sees signaled mres2!");
Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet);
// It's good form to Dispose() a ManualResetEventSlim when you're done with it
observer.Wait(); // make sure that this has fully completed
mres1.Dispose();
mres2.Dispose();
mres3.Dispose();
}
// Demonstrates:
// ManualResetEventSlim construction w/ SpinCount
// ManualResetEventSlim.WaitHandle
static void MRES_SpinCountWaitHandle()
{
// Construct a ManualResetEventSlim with a SpinCount of 1000
// Higher spincount => longer time the MRES will spin-wait before taking lock
ManualResetEventSlim mres1 = new ManualResetEventSlim(false, 1000);
ManualResetEventSlim mres2 = new ManualResetEventSlim(false, 1000);
Task bgTask = Task.Factory.StartNew(() =>
{
// Just wait a little
Thread.Sleep(100);
// Now signal both MRESes
Console.WriteLine("Task signalling both MRESes");
mres1.Set();
mres2.Set();
});
// A common use of MRES.WaitHandle is to use MRES as a participant in
// WaitHandle.WaitAll/WaitAny. Note that accessing MRES.WaitHandle will
// result in the unconditional inflation of the underlying ManualResetEvent.
WaitHandle.WaitAll(new WaitHandle[] { mres1.WaitHandle, mres2.WaitHandle });
Console.WriteLine("WaitHandle.WaitAll(mres1.WaitHandle, mres2.WaitHandle) completed.");
// Clean up
bgTask.Wait();
mres1.Dispose();
mres2.Dispose();
}
}
Imports System.Threading
Imports System.Threading.Tasks
Module MRESDemo
Sub Main()
End Sub
' Demonstrates:
' ManualResetEventSlim construction
' ManualResetEventSlim.Wait()
' ManualResetEventSlim.Set()
' ManualResetEventSlim.Reset()
' ManualResetEventSlim.IsSet
Private Sub MRES_SetWaitReset()
' initialize as unsignaled
Dim mres1 As New ManualResetEventSlim(False)
' initialize as unsignaled
Dim mres2 As New ManualResetEventSlim(False)
' initialize as signaled
Dim mres3 As New ManualResetEventSlim(True)
' Start an asynchronous Task that manipulates mres3 and mres2
Dim observer = Task.Factory.StartNew(
Sub()
mres1.Wait()
Console.WriteLine("observer sees signaled mres1!")
Console.WriteLine("observer resetting mres3...")
mres3.Reset()
' should switch to unsignaled
Console.WriteLine("observer signalling mres2")
mres2.[Set]()
End Sub)
Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet)
Console.WriteLine("main thread signalling mres1")
mres1.[Set]()
' This will "kick off" the observer Task
mres2.Wait()
' This won't return until observer Task has finished resetting mres3
Console.WriteLine("main thread sees signaled mres2!")
Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet)
' make sure that observer has fully completed
observer.Wait()
' It's good form to Dispose() a ManualResetEventSlim when you're done with it
mres1.Dispose()
mres2.Dispose()
mres3.Dispose()
End Sub
' Demonstrates:
' ManualResetEventSlim construction w/ SpinCount
' ManualResetEventSlim.WaitHandle
Private Sub MRES_SpinCountWaitHandle()
' Construct a ManualResetEventSlim with a SpinCount of 1000
' Higher spincount => longer time the MRES will spin-wait before taking lock
Dim mres1 As New ManualResetEventSlim(False, 1000)
Dim mres2 As New ManualResetEventSlim(False, 1000)
Dim bgTask As Task = Task.Factory.StartNew(
Sub()
' Just wait a little
Thread.Sleep(100)
' Now signal both MRESes
Console.WriteLine("Task signalling both MRESes")
mres1.[Set]()
mres2.[Set]()
End Sub)
' A common use of MRES.WaitHandle is to use MRES as a participant in
' WaitHandle.WaitAll/WaitAny. Note that accessing MRES.WaitHandle will
' result in the unconditional inflation of the underlying ManualResetEvent.
WaitHandle.WaitAll(New WaitHandle() {mres1.WaitHandle, mres2.WaitHandle})
Console.WriteLine("WaitHandle.WaitAll(mres1.WaitHandle, mres2.WaitHandle) completed.")
' Wait for bgTask to complete and clean up
bgTask.Wait()
mres1.Dispose()
mres2.Dispose()
End Sub
End Module
설명
대기 시간이 매우 짧을 것으로 예상되는 경우와 이벤트가 프로세스 경계를 넘지 않는 경우보다 ManualResetEvent 성능 향상을 위해 이 클래스를 사용할 수 있습니다. ManualResetEventSlim에서는 이벤트에 신호가 전달되기를 기다리는 짧은 시간 동안 고속 회전을 사용합니다. 대기 시간이 짧은 경우 대기 핸들을 사용하여 기다리는 것보다 회전하는 것이 비용이 적게 들 수 있습니다. 그러나 이벤트가 특정 기간 내에 신호를 받지 않는 경우 일반적인 이벤트 핸들 대기에 ManualResetEventSlim을 사용합니다.
참고
.NET Core 및 .NET 5 이상에서는 플랫폼 및 프로세서에 따라 기본 스핀 대기 기간이 10초 단위로 짧습니다. 대기 시간이 그보다 훨씬 길어질 것으로 예상되는 경우에도 이 클래스를 ManualResetEvent 대신 사용할 수 있습니다(아마도 스핀 대기 시간이 적거나 전혀 없는 것으로 구성됨). 그러나 성능 이점은 미미할 수 있습니다.
생성자
ManualResetEventSlim() |
신호 없음을 초기 상태로 사용하여 ManualResetEventSlim 클래스의 새 인스턴스를 초기화합니다. |
ManualResetEventSlim(Boolean) |
초기 상태를 신호 받음으로 설정할지 여부를 나타내는 부울 값을 사용하여 ManualResetEventSlim 클래스의 새 인스턴스를 초기화합니다. |
ManualResetEventSlim(Boolean, Int32) |
초기 상태를 신호 받음으로 설정할지 여부를 나타내는 부울 값과 지정된 회전 수를 사용하여 ManualResetEventSlim 클래스의 새 인스턴스를 초기화합니다. |
속성
IsSet |
이벤트가 설정되었는지를 가져옵니다. |
SpinCount |
커널 기반의 대기 작업으로 대체하기 전에 수행되는 회전 대기 수를 가져옵니다. |
WaitHandle |
이 WaitHandle의 내부 ManualResetEventSlim 개체를 가져옵니다. |
메서드
Dispose() |
ManualResetEventSlim 클래스의 현재 인스턴스에서 사용하는 모든 리소스를 해제합니다. |
Dispose(Boolean) |
ManualResetEventSlim에서 사용하는 관리되지 않는 리소스를 해제하고, 관리되는 리소스를 선택적으로 해제할 수 있습니다. |
Equals(Object) |
지정된 개체가 현재 개체와 같은지 확인합니다. (다음에서 상속됨 Object) |
GetHashCode() |
기본 해시 함수로 작동합니다. (다음에서 상속됨 Object) |
GetType() |
현재 인스턴스의 Type을 가져옵니다. (다음에서 상속됨 Object) |
MemberwiseClone() |
현재 Object의 단순 복사본을 만듭니다. (다음에서 상속됨 Object) |
Reset() |
스레드가 차단되도록 이벤트 상태를 신호 없음으로 설정합니다. |
Set() |
이벤트에서 대기 중인 하나 이상의 스레드가 계속 진행되도록 이벤트 상태를 신호 받음으로 설정합니다. |
ToString() |
현재 개체를 나타내는 문자열을 반환합니다. (다음에서 상속됨 Object) |
Wait() |
현재 ManualResetEventSlim이 설정될 때까지 현재 스레드를 차단합니다. |
Wait(CancellationToken) |
ManualResetEventSlim을 확인하면서 현재 CancellationToken이 신호를 받을 때까지 현재 스레드를 차단합니다. |
Wait(Int32) |
부호 있는 32비트 정수로 시간 간격을 측정하여 현재 ManualResetEventSlim이 설정될 때까지 현재 스레드를 차단합니다. |
Wait(Int32, CancellationToken) |
ManualResetEventSlim을 확인하면서 부호 있는 32비트 정수로 시간 간격을 측정하여 현재 CancellationToken이 설정될 때까지 현재 스레드를 차단합니다. |
Wait(TimeSpan) |
ManualResetEventSlim으로 시간 간격을 측정하여 현재 TimeSpan이 설정될 때까지 현재 스레드를 차단합니다. |
Wait(TimeSpan, CancellationToken) |
ManualResetEventSlim을 확인하면서 TimeSpan으로 시간 간격을 측정하여 현재 CancellationToken이 설정될 때까지 현재 스레드를 차단합니다. |
적용 대상
스레드 보안
모든 공용 및 보호된 멤버 ManualResetEventSlim 는 스레드로부터 안전하며 여러 스레드에서 동시에 사용할 수 있습니다. 단, Dispose는 다른 모든 작업이 ManualResetEventSlim 완료된 경우에만 사용해야 하며 다시 설정은 다른 스레드가 이벤트에 액세스하지 않는 경우에만 사용해야 합니다.