CEvent
クラス
イベントを表します。これは、あるスレッドがイベントが発生したことを別のスレッドに通知できるようにする同期オブジェクトです。
構文
class CEvent : public CSyncObject
メンバー
パブリック コンストラクター
名前 | 説明 |
---|---|
CEvent::CEvent |
CEvent オブジェクトを構築します。 |
パブリック メソッド
名前 | 説明 |
---|---|
CEvent::PulseEvent |
イベントを使用可能 (シグナル) に設定し、待機中のスレッドを解放し、イベントを使用不可 (非割り当て) に設定します。 |
CEvent::ResetEvent |
イベントを使用不可 (非署名) に設定します。 |
CEvent::SetEvent |
イベントを使用可能 (シグナル) に設定し、待機しているスレッドを解放します。 |
CEvent::Unlock |
イベント オブジェクトを解放します。 |
解説
イベントは、スレッドがそのタスクを実行するタイミングを知る必要がある場合に便利です。 たとえば、データアーカイブにデータをコピーするスレッドは、新しいデータが使用可能になったときに通知を受け取る必要があります。 オブジェクトを CEvent
使用して、新しいデータが使用可能になったときにコピー スレッドに通知することで、スレッドはできるだけ早くタスクを実行できます。
CEvent
オブジェクトには、手動と自動の 2 種類があります。
自動 CEvent
オブジェクトは、少なくとも 1 つのスレッドが解放された後、非シグナル状態 (使用不可) に自動的に戻ります。 既定では、構築中にパラメーターを CEvent
渡 TRUE
さない限り、 bManualReset
オブジェクトは自動です。
手動CEvent
オブジェクトは、他の関数が呼び出されるまで設定されたSetEvent
ResetEvent
状態のままです。 手動CEvent
オブジェクトを作成するには、構築中にパラメーターをbManualReset
渡TRUE
します。
オブジェクトを CEvent
使用するには、必要に応じてオブジェクトを CEvent
構築します。 待機するイベントの名前を指定し、アプリケーションが最初にイベントを所有するように指定します。 その後、コンストラクターが戻ったときにイベントにアクセスできます。 イベント オブジェクトを通知 (使用可能にする) を呼び出 SetEvent
し、制御されたリソースへのアクセスが完了したら呼び出 Unlock
します。
オブジェクトを使用 CEvent
する別の方法は、制御するクラスにデータ メンバーとして型 CEvent
の変数を追加することです。 制御されたオブジェクトの構築中に、データ メンバーのコンストラクターを CEvent
呼び出し、イベントが最初に通知されるかどうかを指定し、必要なイベント オブジェクトの種類、イベントの名前 (プロセス境界を越えて使用される場合)、および必要なセキュリティ属性を指定します。
この方法でオブジェクトによって制御されるCEvent
リソースにアクセスするには、まず、リソースのアクセス方法で型または型CSingleLock
CMultiLock
のいずれかの変数を作成します。 次に、オブジェクトの Lock
メソッドを lock
呼び出します (例: CMultiLock::Lock
)。 この時点で、スレッドはリソースへのアクセス権を取得するか、リソースが解放されてアクセスを得るのを待つか、リソースが解放されるのを待ってタイムアウトし、リソースへのアクセスに失敗します。 いずれの場合も、リソースにはスレッド セーフな方法でアクセスされています。 リソースを解放するには、イベント オブジェクトを通知する呼び出しを呼び出SetEvent
し、オブジェクトのlock
メソッド (たとえば、) を使用Unlock
するか、CMultiLock::Unlock
オブジェクトがlock
スコープ外に落ちることを許可します。
オブジェクトの使用方法CEvent
の詳細については、「マルチスレッド: 同期クラスを使用する方法」を参照してください。
例
// The following demonstrates trivial usage of the CEvent class.
// A CEvent object is created and passed as a parameter to another
// thread. The other thread will wait for the event to be signaled
// and then exit
UINT __cdecl MyThreadProc(LPVOID lpParameter)
{
CEvent *pEvent = (CEvent *)(lpParameter);
VERIFY(pEvent != NULL);
// Wait for the event to be signaled
::WaitForSingleObject(pEvent->m_hObject, INFINITE);
// Terminate the thread
::AfxEndThread(0, FALSE);
return 0L;
}
void CEvent_Test()
{
// Create the CEvent object that will be passed to the thread routine
CEvent *pEvent = new CEvent(FALSE, FALSE);
// Create a thread that will wait on the event
CWinThread *pThread;
pThread = ::AfxBeginThread(&MyThreadProc, pEvent, 0, 0, CREATE_SUSPENDED, NULL);
pThread->m_bAutoDelete = FALSE;
pThread->ResumeThread();
// Signal the thread to do the next work item
pEvent->SetEvent();
// Wait for the thread to consume the event and return
::WaitForSingleObject(pThread->m_hThread, INFINITE);
delete pThread;
delete pEvent;
}
// This example builds upon the previous one.
// A second thread is created to calculate prime numbers.
// The main thread will signal the second thread to calculate the next
// prime number in the series. The second thread signals the first
// after each number is calculated. Finally, after several iterations
// the worker thread is signaled to terminate.
class CPrimeTest
{
public:
CPrimeTest()
: m_pCalcNext(new CEvent(FALSE, FALSE)),
m_pCalcFinished(new CEvent(FALSE, FALSE)),
m_pTerminateThread(new CEvent(FALSE, FALSE)),
m_iCurrentPrime(0)
{
// Create a thread that will calculate the prime numbers
CWinThread *pThread;
pThread = ::AfxBeginThread(&PrimeCalcProc,
this, 0, 0, CREATE_SUSPENDED, NULL);
pThread->m_bAutoDelete = FALSE;
pThread->ResumeThread();
// Calcuate the first 10 prime numbers in the series on the thread
for (UINT i = 0; i < 10; i++)
{
// Signal the thread to do the next work item
m_pCalcNext->SetEvent();
// Wait for the thread to complete the current task
::WaitForSingleObject(m_pCalcFinished->m_hObject, INFINITE);
// Print the result
TRACE(_T("The value of m_iCurrentPrime is: %d\n"), m_iCurrentPrime);
}
// Notify the worker thread to exit and wait for it to complete
m_pTerminateThread->SetEvent();
::WaitForSingleObject(pThread->m_hThread, INFINITE);
delete pThread;
}
~CPrimeTest()
{
delete m_pCalcNext;
delete m_pCalcFinished;
delete m_pTerminateThread;
}
private:
// Determines whether the given number is a prime number
static BOOL IsPrime(INT ThisPrime)
{
if (ThisPrime < 2)
return FALSE;
for (INT n = 2; n < ThisPrime; n++)
{
if (ThisPrime % n == 0)
return FALSE;
}
return TRUE;
}
// Calculates the next prime number in the series
static INT NextPrime(INT ThisPrime)
{
while (TRUE)
{
if (IsPrime(++ThisPrime))
{
return ThisPrime;
}
}
}
// Worker thread responsible for calculating the next prime
// number in the series
static UINT __cdecl PrimeCalcProc(LPVOID lpParameter)
{
CPrimeTest *pThis = static_cast<CPrimeTest *>(lpParameter);
VERIFY(pThis != NULL);
VERIFY(pThis->m_pCalcNext != NULL);
VERIFY(pThis->m_pCalcFinished != NULL);
VERIFY(pThis->m_pTerminateThread != NULL);
// Create a CMultiLock object to wait on the various events
// WAIT_OBJECT_0 refers to the first event in the array,
// WAIT_OBJECT_0+1 refers to the second
CSyncObject *pWaitObjects[] = {pThis->m_pCalcNext,
pThis->m_pTerminateThread};
CMultiLock MultiLock(pWaitObjects, 2L);
while (MultiLock.Lock(INFINITE, FALSE) == WAIT_OBJECT_0)
{
// Calculate next prime
pThis->m_iCurrentPrime = NextPrime(pThis->m_iCurrentPrime);
// Notify main thread calculation is complete
pThis->m_pCalcFinished->SetEvent();
}
// Terminate the thread
::AfxEndThread(0, FALSE);
return 0L;
}
CEvent *m_pCalcNext; // notifies worker thread to calculate next prime
CEvent *m_pCalcFinished; // notifies main thread current calculation is complete
CEvent *m_pTerminateThread; // notifies worker thread to terminate
INT m_iCurrentPrime; // current calculated prime number
};
継承階層
CEvent
必要条件
ヘッダー:afxmt.h
CEvent::CEvent
名前付きオブジェクトまたは名前のないオブジェクトを CEvent
構築します。
CEvent(
BOOL bInitiallyOwn = FALSE,
BOOL bManualReset = FALSE,
LPCTSTR lpszName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttribute = NULL);
パラメーター
bInitiallyOwn
場合TRUE
は、またはCSingleLock
オブジェクトのCMultilock
スレッドが有効です。 それ以外の場合、リソースにアクセスするすべてのスレッドは待機する必要があります。
bManualReset
の場合 TRUE
は、イベント オブジェクトが手動イベントであることを指定します。それ以外の場合、イベント オブジェクトは自動イベントです。
lpszName
CEvent
オブジェクトの名前。 オブジェクトがプロセス境界を越えて使用される場合は、指定する必要があります。 名前が既存のイベントと一致する場合、コンストラクターはその名前のイベントを参照する新しい CEvent
オブジェクトをビルドします。 名前がイベントではない既存の同期オブジェクトと一致する場合、構築は失敗します。 の場合 NULL
、名前は null になります。
lpsaAttribute
イベント オブジェクトのセキュリティ属性。 この構造の詳細については、Windows SDK を参照してください SECURITY_ATTRIBUTES
。
解説
オブジェクトにアクセスまたは解放CEvent
するには、オブジェクトをCMultiLock
CSingleLock
作成し、そのオブジェクトとUnlock
メンバー関数をLock
呼び出します。
オブジェクトの状態を CEvent
シグナル通知に変更するには (スレッドは待機する必要はありません)、呼び出し SetEvent
または PulseEvent
. オブジェクトの CEvent
状態を非署名 (スレッドは待機する必要があります) に設定するには、次を呼び出します ResetEvent
。
重要
オブジェクトを作成した CEvent
後、ミューテックスがまだ存在していないことを確認するために使用 GetLastError
します。 ミューテックスが予期せず存在していた場合は、不正なプロセスがしゃがみ込み、ミューテックスを悪意を持って使用しようとしている可能性があることを示している可能性があります。 この場合、推奨されるセキュリティ意識の高い手順は、ハンドルを閉じて、オブジェクトの作成に失敗したかのように続行することです。
CEvent::PulseEvent
イベントの状態をシグナル通知 (使用可能) に設定し、待機中のスレッドをすべて解放し、自動的に非署名 (使用不可) にリセットします。
BOOL PulseEvent();
戻り値
関数が成功した場合は 0 以外。それ以外の場合は 0。
解説
イベントが手動の場合、待機しているすべてのスレッドが解放され、イベントは非署名に設定され PulseEvent
、返されます。 イベントが自動で、1 つのスレッドが解放され、イベントが非署名に設定され PulseEvent
、返されます。
待機しているスレッドがない場合、またはスレッドをすぐに解放できない場合は、 PulseEvent
イベントの状態を非署名に設定して返します。
PulseEvent
は基になる Win32 PulseEvent
関数を使用します。これは、カーネル モードの非同期プロシージャ呼び出しによって待機状態から一時的に削除される可能性があります。 そのため、信頼性が低く、 PulseEvent
新しいアプリケーションでは使用しないでください。 詳細については、PulseEvent
関数に関するページを参照してください。
CEvent::ResetEvent
メンバー関数によってシグナル通知に明示的に設定されるまで、イベントの状態を非署名に SetEvent
設定します。
BOOL ResetEvent();
戻り値
関数が成功した場合は 0 以外。それ以外の場合は 0。
解説
これにより、このイベントにアクセスするすべてのスレッドが待機します。
このメンバー関数は、自動イベントでは使用されません。
CEvent::SetEvent
イベントの状態をシグナル通知に設定し、待機中のスレッドを解放します。
BOOL SetEvent();
戻り値
関数が成功した場合は 0 以外、それ以外の場合は 0。
解説
イベントが手動の場合、イベントは再メイン呼び出されるまでResetEvent
通知されます。 この場合、複数のスレッドを解放できます。 イベントが自動の場合、1 つのスレッドが解放されるまでメインイベントが再通知されます。 その後、システムはイベントの状態を非署名に設定します。 待機しているスレッドがない場合は、1 つのスレッドが解放されるまで状態が再メイン通知されます。
CEvent::Unlock
イベント オブジェクトを解放します。
BOOL Unlock();
戻り値
スレッドがイベント オブジェクトを所有していて、イベントが自動イベントの場合は 0 以外。それ以外の場合は 0。
解説
このメンバー関数は、オブジェクトが再利用される場合 lock
に、完了した後に解放する自動イベントを現在所有しているスレッドによって呼び出されます。 オブジェクトを lock
再利用しない場合、この関数はオブジェクトの lock
デストラクターによって呼び出されます。
関連項目
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示