ManualResetEvent
是 C# 中的一個(gè)同步原語(yǔ),它允許一個(gè)或多個(gè)線程等待,直到另一個(gè)線程設(shè)置一個(gè)事件。ManualResetEvent
的信號(hào)控制主要通過(guò)其 Set()
和 Reset()
方法來(lái)實(shí)現(xiàn)。
Set()
方法時(shí),如果 ManualResetEvent
當(dāng)前處于未信號(hào)狀態(tài)(即沒(méi)有線程在等待),則它會(huì)被設(shè)置為信號(hào)狀態(tài)。如果有線程正在等待,那么這些線程會(huì)立即被釋放并繼續(xù)執(zhí)行。如果 ManualResetEvent
已經(jīng)是信號(hào)狀態(tài),那么調(diào)用 Set()
方法不會(huì)有任何效果。Reset()
方法時(shí),ManualResetEvent
會(huì)被設(shè)置為非信號(hào)狀態(tài)。這意味著任何正在等待該事件的線程都會(huì)被阻塞,直到再次調(diào)用 Set()
方法將其設(shè)置為信號(hào)狀態(tài)。以下是一個(gè)簡(jiǎn)單的示例,展示了如何使用 ManualResetEvent
來(lái)同步線程:
using System;
using System.Threading;
class Program
{
static ManualResetEvent _event = new ManualResetEvent(false); // 初始化為非信號(hào)狀態(tài)
static void Main()
{
Thread thread1 = new Thread(DoWork);
Thread thread2 = new Thread(DoWork);
thread1.Start();
thread2.Start();
// 讓線程1先執(zhí)行
_event.Set();
thread1.Join();
thread2.Join();
}
static void DoWork()
{
Console.WriteLine("Thread is waiting for event...");
_event.WaitOne(); // 等待事件被設(shè)置為信號(hào)狀態(tài)
Console.WriteLine("Event received. Thread continues.");
}
}
在這個(gè)示例中,我們創(chuàng)建了兩個(gè)線程 thread1
和 thread2
,它們都調(diào)用 DoWork
方法。在 Main
方法中,我們首先啟動(dòng)這兩個(gè)線程,然后調(diào)用 _event.Set()
來(lái)設(shè)置事件,使得 thread1
可以立即繼續(xù)執(zhí)行。thread1
執(zhí)行完畢后,主線程調(diào)用 Join()
等待兩個(gè)線程都執(zhí)行完畢。
需要注意的是,ManualResetEvent
的信號(hào)狀態(tài)只能由一個(gè)線程來(lái)設(shè)置,其他線程必須等待該事件被設(shè)置后才能繼續(xù)執(zhí)行。如果多個(gè)線程同時(shí)調(diào)用 Set()
方法,那么只有第一個(gè)調(diào)用的線程會(huì)成功設(shè)置事件狀態(tài),其他線程會(huì)拋出異常。為了避免這種情況,可以使用 Monitor
或其他同步原語(yǔ)來(lái)確保只有一個(gè)線程能夠設(shè)置事件狀態(tài)。