~Thread() {
CloseHandle(_handle);
}
void Resume() {
ResumeThread(_handle);
}
void WaitForDeath() {
WaitForSingleObject(_handle, 2000);
}
private:
HANDLE _handle;
DWORD _tid; // thread id
};
Π‘ΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ β ΡΡΠΎ ΡΠΎ, ΡΡΠΎ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π΄Π΅Π»Π°Π΅Ρ ΠΌΠ½ΠΎΠ³ΠΎΠ·Π°Π΄Π°ΡΠ½ΡΠΉ ΡΠ΅ΠΆΠΈΠΌ ΡΡΠΎΠ»Ρ ΠΈΠ½ΡΠ΅Π½ΡΠΈΠ²Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠΌ. ΠΠ°Π²Π°ΠΉΡΠ΅, Π½Π°ΡΠ½Π΅ΠΌ ΡΠΎ Π²Π·Π°ΠΈΠΌΠ½ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ. ΠΠ»Π°ΡΡ Mutex β ΡΠΎΠ½ΠΊΠ°Ρ ΠΈΠ½ΠΊΠ°ΠΏΡΡΠ»ΡΡΠΈΡ API. ΠΡ Π²Π½Π΅Π΄ΡΡΠ΅ΡΠ΅ Mutexes (ΠΌΡΡΠ°ΡΠΈΠΈ) Π² Π²Π°Ρ ΠΠΊΡΠΈΠ²Π½ΡΠΉ ΠΠ±ΡΠ΅ΠΊΡ, Π° Π·Π°ΡΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΠ΅ ΠΈΡ ΡΠ΅ΡΠ΅Π· ΠΠ»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ. ΠΠ»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ° (Lock) β ΡΠΌΠ½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΎΠ·Π΄Π°Π΅ΡΡΡ Π½Π° ΡΡΠ΅ΠΊΠ΅. Π ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ ΡΠ΅Π³ΠΎ, Π²ΠΎ Π²ΡΠ΅ΠΌΡ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ, Π²Π°Ρ ΠΎΠ±ΡΠ΅ΠΊΡ Π·Π°ΡΠΈΡΠ΅Π½ ΠΎΡ Π»ΡΠ±ΡΡ Π΄ΡΡΠ³ΠΈΡ ΠΏΠΎΡΠΎΠΊΠΎΠ². ΠΠ»Π°ΡΡ Lock β ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΠ΅ΡΡΡΡΠ°ΠΌΠΈ. ΠΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΠΎΠΌΠ΅ΡΡΠΈΡΡ Lock Π²Π½ΡΡΡΠΈ Π²ΡΠ΅Ρ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² Π²Π°ΡΠ΅Π³ΠΎ ΠΠΊΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΠ±ΡΠ΅ΠΊΡΠ°, ΠΊΠΎΡΠΎΡΡΠ΅ ΡΠ°Π·Π΄Π΅Π»ΡΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ Π΄Π°Π½Π½ΡΠΌ Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΠΏΠΎΡΠΎΠΊΠ°ΠΌΠΈ.
class Mutex {
friend class Lock;
public:
Mutex() {
InitializeCriticalSection(&_critSection);
}
~Mutex() {
DeleteCriticalSection(&_critSection);
}
private:
void Acquire() {
EnterCriticalSection(&_critSection);
}
void Release() {
LeaveCriticalSection(&_critSection);
}
CRITICAL_SECTION _critSection;
};
class Lock {
public:
// Acquire the state of the semaphore
Lock(Mutex& mutex) : _mutex(mutex) {
_mutex.Acquire();
}
// Release the state of the semaphore
~Lock() {
_mutex.Release();
}
private:
Mutex& _mutex;
};
Π‘ΠΎΠ±ΡΡΠΈΠ΅ β ΡΡΠΎ ΡΠΈΠ³Π½Π°Π»ΡΠ½ΠΎΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΏΠΎΡΠΎΠΊΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ, ΡΡΠΎΠ±Ρ ΡΠ²ΡΠ·Π°ΡΡΡΡ Π΄ΡΡΠ³ Ρ Π΄ΡΡΠ³ΠΎΠΌ. ΠΡ Π²Π½Π΅Π΄ΡΡΠ΅ΡΠ΅ Π‘ΠΎΠ±ΡΡΠΈΠ΅ (Event) Π² Π²Π°Ρ Π°ΠΊΡΠΈΠ²Π½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ. ΠΠ°ΡΠ΅ΠΌ ΠΡ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄ΠΈΡΠ΅ ΡΠ΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΡΠΉ ΠΏΠΎΡΠΎΠΊ Π² ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ, ΠΏΠΎΠΊΠ° Π½Π΅ΠΊΠΎΡΠΎΡΡΠΉ Π΄ΡΡΠ³ΠΎΠΉ ΠΏΠΎΡΠΎΠΊ Π½Π΅ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ Π΅Π³ΠΎ. ΠΠ΅ Π·Π°Π±ΡΠ΄ΡΡΠ΅ ΠΎΠ΄Π½Π°ΠΊΠΎ, ΡΡΠΎ, Π΅ΡΠ»ΠΈ Π²Π°Ρ ΡΠ΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΠΉ ΠΏΠΎΡΠΎΠΊ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ ΡΠΎΠ±ΡΡΠΈΡ, ΠΎΠ½ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π·Π°Π²Π΅ΡΡΠ΅Π½. ΠΠΌΠ΅Π½Π½ΠΎ ΠΏΠΎΡΡΠΎΠΌΡ ΠΡ Π΄ΠΎΠ»ΠΆΠ½Ρ Π²ΡΠ·ΡΠ²Π°ΡΡ Release ΠΈΠ· ΠΌΠ΅ΡΠΎΠ΄Π° Flush.
class Event {
public:
Event() {
// start in non-signaled state (red light)
// auto reset after every Wait
_handle = CreateEvent(0, FALSE, FALSE, 0);
}
~Event() {
CloseHandle(_handle);
}
// put into signaled state
void Release() {
SetEvent(_handle);
}
void Wait() {
// Wait until event is in signaled (green) state
WaitForSingleObject(_handle, INFINITE);
}
operator HANDLE() { return _handle; }
private:
HANDLE _handle;
};
Π§ΡΠΎΠ±Ρ ΡΠ²ΠΈΠ΄Π΅ΡΡ, ΠΊΠ°ΠΊ ΡΡΠΈ ΠΊΠ»Π°ΡΡΡ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½Ρ, Ρ ΠΏΡΠ΅Π΄Π»Π°Π³Π°Ρ Π½Π΅Π±ΠΎΠ»ΡΡΡΡ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΡ. ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΉΡΠΈ ΠΊ ΡΡΡΠ°Π½ΠΈΡΠ΅, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΎΠ±ΡΡΡΠ½ΡΠ΅Ρ, ΠΊΠ°ΠΊ ΠΊΠ»Π°ΡΡ ActiveObject ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π² Π§Π°ΡΡΠΎΡΠ½ΠΎΠΌ Π°Π½Π°Π»ΠΈΠ·Π°ΡΠΎΡΠ΅ Π΄Π»Ρ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΉ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ Π΄ΠΈΡΠΏΠ»Π΅Π΅Π². ΠΠ»ΠΈ, ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΠ·ΡΡΠΈΡΡ Π±ΠΎΠ»Π΅Π΅ ΠΏΡΠΎΡΡΠΎΠΉ ΠΏΡΠΈΠΌΠ΅Ρ ΠΠ°Π±Π»ΡΠ΄Π°ΡΠ΅Π»Ρ ΠΠ°ΠΏΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΏΠΎΠΊΠΎΠΉΠ½ΠΎ ΠΆΠ΄Π΅Ρ, ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ°Ρ ΠΏΠ°ΠΏΠΊΠΈ, ΠΈ ΠΏΡΠΎΠ±ΡΠΆΠ΄Π°Π΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ, ΠΊΠΎΠ³Π΄Π° ΠΏΡΠΈΡΡ ΠΎΠ΄ΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π΅Π΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ³ΠΎ.
ΠΠ°Π»Ρ, ΡΡΠΎ Ρ Π½Π΅ ΠΌΠΎΠ³Ρ ΡΠΊΠ°Π·Π°ΡΡ, ΡΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΡΠΎΠΊΠΎΠ² ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΏΡΠΎΡΡΡΠΌ. ΠΠ΄Π½Π°ΠΊΠΎ, ΠΎΠ½ΠΎ Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΡΠ΅, Π΅ΡΠ»ΠΈ ΠΡ ΡΡΠ°Π½Π΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΠ΅ ΠΏΡΠΈΠΌΠΈΡΠΈΠ²Ρ. ΠΡΠΎ ΠΏΡΠΈΠΌΠΈΡΠΈΠ²Ρ, ΠΊΠΎΡΠΎΡΡΠ΅ Ρ ΡΠ΅ΠΊΠ»Π°ΠΌΠΈΡΠΎΠ²Π°Π»: ActiveObject, Thread, Mutex, Lock ΠΈ Event. ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΠ· Π½ΠΈΡ ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ Π΄ΠΎΡΡΡΠΏΠ½Ρ Π² MFC. Π ΠΏΡΠΈΠΌΠ΅ΡΡ, ΡΠ°ΠΌ Π΅ΡΡΡ Π±Π»ΠΎΠΊΠΈΡΡΡΡΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ CLock (Π° ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ β ΡΡΠΎ Π§ΠΠ‘Π« [CLock β ΠΈΠ³ΡΠ° ΡΠ»ΠΎΠ²]?) Π΄Π΅ΡΡΡΡΠΊΡΠΎΡ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ, ΠΊΡΠΈΡΠΈΡΠ΅ΡΠΊΠΎΠΉ ΡΠ΅ΠΊΡΠΈΠ΅ΠΉ (ΠΎΠ½ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΅ ΡΠ΄ΠΎΠ±Π΅Π½ ΠΈΠ·-Π·Π° Β«Π΄Π²ΡΡ ΡΠ°Π³ΠΎΠ²ΠΎΠΉΒ» ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ: ΠΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎΠ·Π΄Π°ΡΡ Π΅Π³ΠΎ, Π° Π·Π°ΡΠ΅ΠΌ Π²ΡΠ±ΠΈΡΠ°ΡΡ Π΅Π³ΠΎ Π² Π΄Π²Π° ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ ΡΠ°Π³Π° β ΠΊΠ°ΠΊ Π±ΡΠ΄ΡΠΎ Π±Ρ Π²Ρ Π·Π°Ρ ΠΎΡΠ΅Π»ΠΈ ΡΠΎΠ·Π΄Π°ΡΡ Π΅Π³ΠΎ, Π° Π·Π°ΡΠ΅ΠΌ ΠΏΠ΅ΡΠ΅Π΄ΡΠΌΠ°ΡΡ). ΠΡΡΠ³ΠΎΠ΅ ΠΎΡΠ»ΠΈΡΠΈΠ΅: MFC ΠΏΡΠ΅Π΄Π»Π°Π³Π°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ Π½Π΅ΠΊΠΎΡΠΎΡΡΡ ΡΠΎΠ½ΠΊΡΡ ΡΠ°Π½Π΅ΡΡ Π½Π°Π΄ API ΠΈ Π½ΠΈΡΠ΅Π³ΠΎ Π½ΠΎΠ²ΠΎΠ³ΠΎ.
ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠ°ΠΊΠΆΠ΅ ΡΠ°ΡΠΏΠΎΠ·Π½Π°ΡΡ Π² Π½Π΅ΠΊΠΎΡΠΎΡΡΡ ΠΈΠ· ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΠΎΠ², ΠΊΠΎΡΠΎΡΡΠ΅ Ρ ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΠΈΠ» Π·Π΄Π΅ΡΡ, Π°Π½Π°Π»ΠΎΠ³ΠΈ ΠΈΠ· ΡΠ·ΡΠΊΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ Java. ΠΠΎΠ½Π΅ΡΠ½ΠΎ, ΠΊΠΎΠ³Π΄Π° ΠΡ ΠΈΠΌΠ΅Π΅ΡΠ΅ ΡΠ²ΠΎΠ±ΠΎΠ΄Ρ ΠΏΡΠΎΠ΅ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ½ΠΎΠ³ΠΎΠ·Π°Π΄Π°ΡΠ½ΠΎΠ³ΠΎ ΡΠ΅ΠΆΠΈΠΌΠ° Π² ΡΠ·ΡΠΊΠ΅, ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ ΡΠ΅Π±Π΅ Π±ΡΡΡ ΠΈΠ·ΡΡΠ½ΡΠΌΠΈ. ΠΡ Π²Π΅ΡΡΠΈΡ ActiveObject Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ Runnable, ΠΈ ΠΎΠ½Π° ΠΈΠΌΠ΅Π΅Ρ ΠΌΠ΅ΡΠΎΠ΄ run. ΠΠ°ΠΆΠ΄ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Java ΠΏΠΎΡΠ΅Π½ΡΠΈΠ°Π»ΡΠ½ΠΎ ΠΈΠΌΠ΅Π΅Ρ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΉ mutex ΠΈ Π²ΡΠ΅, ΡΡΠΎ ΠΠ°ΠΌ Π½Π°Π΄ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ, ΡΡΠΎΠ±Ρ ΠΎΡΡΡΠ΅ΡΡΠ²ΠΈΡΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΡ, β ΡΡΠΎ ΠΎΠ±ΡΡΠ²ΠΈΡΡ ΠΌΠ΅ΡΠΎΠ΄ (ΠΈΠ»ΠΈ ΠΎΠ±Π»Π°ΡΡΡ) Π·Π°ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌ. Π’ΠΎΡΠ½ΠΎ ΡΠ°ΠΊ ΠΆΠ΅ ΡΠΎΠ±ΡΡΠΈΡ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΡΠ΅ Ρ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡΠΌΠΈ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡΠΌΠΈ Π²ΡΠ·ΡΠ²Π°ΡΡΡΡ Π²Π½ΡΡΡΠΈ Π»ΡΠ±ΠΎΠ³ΠΎ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅ΡΠΎΠ΄Π°. ΠΠΎΡΡΠΎΠΌΡ, Π΅ΡΠ»ΠΈ ΠΡ Π·Π½Π°Π΅ΡΠ΅, ΠΊΠ°ΠΊ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°ΡΡ Π½Π° Java, ΠΡ Π·Π½Π°Π΅ΡΠ΅, ΠΊΠ°ΠΊ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°ΡΡ Π½Π° C++ (ΠΊΠ°ΠΊ Π±ΡΠ΄ΡΠΎ Π΅ΡΡΡ Π·Π½Π°ΡΠΎΠΊΠΈ Java, Π½Π΅ ΠΎΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½Π½ΡΠ΅ ΠΎ C++).
ΠΠ°Π»Π΅Π΅: ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΡΠΎΠΊΠΎΠ² Π½Π° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΠΠ°Π±Π»ΡΠ΄Π°ΡΠ΅Π»Ρ Π·Π° ΠΏΠ°ΠΏΠΊΠ°ΠΌΠΈ.
ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΡΠΎΠΊΠΎΠ²
ΠΠ΅ΡΠ΅Π²ΠΎΠ΄ Π. Π. ΠΠ΅Π³Π°Π»ΠΎΠ²Π°
ΠΠ½Π³Π»ΠΎΡΠ·ΡΡΠ½ΡΠΉ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π» Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠ΅ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ Reliable Software
ΠΡ ΠΊΠΎΠ³Π΄Π°-Π»ΠΈΠ±ΠΎ Π·Π°Π΄Π°Π»ΠΈΡΡ Π²ΠΎΠΏΡΠΎΡΠΎΠΌ: ΠΊΠ°ΠΊΠΈΠΌ ΠΎΡΠ°Π·ΠΎΠΌ ΠΡΠΎΠ²ΠΎΠ΄Π½ΠΈΠΊ (Explorer) ΡΠ·Π½Π°Π΅Ρ ΠΎ ΡΠΎΠΌ, ΡΡΠΎ Π½Π΅ΠΊΠΎΡΠΎΡΠΎΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΌΠΎΠ΄ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°ΡΡ Π΅Π³ΠΎ ΠΎΠΊΠ½ΠΎ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Π±ΡΠ» Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ ΠΈΠ»ΠΈ ΡΠ΄Π°Π»Π΅Π½ ΡΠ°ΠΉΠ» Π² ΡΠ΅ΠΊΡΡΠ΅ΠΉ ΠΏΠ°ΠΏΠΊΠ΅ Π½Π΅ΠΊΠΎΡΠΎΡΡΠΌ Π²Π½Π΅ΡΠ½ΠΈΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ? ΠΠΎΠ»ΡΡΠ΅ ΡΡΠΎΠΌΡ ΠΌΠΎΠΆΠ½ΠΎ Π½Π΅ ΡΠ΄ΠΈΠ²Π»ΡΡΡΡΡ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π°ΡΠ΅Π³ΠΎ ΠΠΊΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΠ±ΡΠ΅ΠΊΡΠ° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π΄Π΅Π»Π°ΡΡ ΡΠΎ ΠΆΠ΅ ΡΠ°ΠΌΠΎΠ΅ ΠΈ Π΄Π°ΠΆΠ΅ Π±ΠΎΠ»ΡΡΠ΅. ΠΡΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΎΡΡΡΡ Π²ΡΠ·ΠΎΠ²ΠΎΠ² API, Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΊΠΎΡΠΎΡΡΡ ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π·Π°ΠΏΡΠΎΡΠΈΡΡ Ρ ΡΠ°ΠΉΠ»ΠΎΠ²ΠΎΠΉ ΡΠΈΡΡΠ΅ΠΌΡ, ΡΡΠΎΠ±Ρ ΠΎΠ½Π° ΠΈΠ·Π±ΠΈΡΠ°ΡΠ΅Π»ΡΠ½ΠΎ ΡΠΎΠΎΠ±ΡΠΈΠ»Π° ΠΠ°ΠΌ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π΄Π»Ρ ΡΠ°ΠΉΠ»ΠΎΠ² ΠΈ ΠΏΠ°ΠΏΠΎΠΊ. ΠΠ°ΠΊ ΡΠΎΠ»ΡΠΊΠΎ ΠΡ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΡΠ΅ ΡΠ°ΠΊΡΡ Π²Π°Ρ ΡΡ, Π²Π°Ρ ΠΏΠΎΡΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ ΡΠΏΠ°ΡΡ, ΠΎΠΆΠΈΠ΄Π°Ρ ΠΏΡΠΈΡ ΠΎΠ΄Π° ΡΠΎΠ±ΡΡΠΈΠΉ. Π€Π°ΠΉΠ»ΠΎΠ²Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° ΠΎΡΡΠ΅Π°Π³ΠΈΡΡΠ΅Ρ Π½Π° ΡΠΎΠ±ΡΡΠΈΠ΅, ΠΊΠ°ΠΊ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ½Π° ΠΎΠ±Π½Π°ΡΡΠΆΠΈΡ Π²ΠΈΠ΄ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ, Π·Π° ΠΊΠΎΡΠΎΡΡΠΌ Π²Ρ Π½Π°Π±Π»ΡΠ΄Π°Π΅ΡΠ΅.
ΠΠ°Π³ΡΡΠ·ΠΊΠ° ΠΈΡΡ ΠΎΠ΄Π½ΡΡ ΡΠ΅ΠΊΡΡΠΎΠ² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ FolderWatcher (zip Π°ΡΡ ΠΈΠ² 11K).
ΠΠ΅Π· Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅ΠΉ ΡΡΠ΅ΡΡ ΡΠ½Π°ΡΠ»Π΅Π΄ΡΠ΅ΠΌ FolderWatcher ΠΈΠ· ActiveObject. ΠΠ°Π΄Π°Π΄ΠΈΠΌ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ° ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡ β ΡΠΎΠ±ΡΡΠΈΠ΅, Π° Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΠΊΠ° ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡ β Π΄Π΅ΡΠΊΡΠΈΠΏΡΠΎΡ ΠΊ ΠΎΠΊΠ½Π°, ΠΎΡΠ²Π΅ΡΠ°ΡΡΠ΅Π³ΠΎ Π½Π° ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠ΅. ΠΡΡ ΠΎΠ΄Π½ΠΎΠ΅ ΡΠΎΠ±ΡΡΠΈΠ΅ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΎ Π² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ΅ FolderWatcher. ΠΠ°ΠΆΠ½ΠΎ ΡΠ°ΠΊΠΆΠ΅ Π·Π°ΠΏΡΡΡΠΈΡΡ ΡΠ΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΡΠΉ ΠΏΠΎΡΠΎΠΊ Π² ΠΊΠΎΠ½ΡΠ΅ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ°.
class FolderWatcher : public ActiveObject {
public: FolderWatcher(char const* folder, HWND hwnd) : _notifySource (folder), _hwndNotifySink (hwnd) {
strcpy(_folder, folder);
_thread.Resume();
}
~FolderWatcher() {
Kill();
}
private:
void InitThread() {}
void Loop();
void FlushThread() {}
FolderChangeEvent _notifySource;
HWND _hwndNotifySink;
char _folder[MAX_PATH];
};
ΠΡΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ Π² ActiveObject ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΡΡ Π²Π½ΡΡΡΠΈ ΠΌΠ΅ΡΠΎΠ΄Π° Loop. ΠΠ΄Π΅ΡΡ ΠΌΡ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ "Π±Π΅ΡΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ" ΡΠΈΠΊΠ», Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΠΏΠΎΡΠΎΠΊ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΠΆΠΈΠ΄Π°ΡΡ ΡΠΎΠ±ΡΡΠΈΠ΅. ΠΠΎΠ³Π΄Π° ΡΠΎΠ±ΡΡΠΈΠ΅ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ, ΠΌΡ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΠ»Π°ΠΆΠΎΠΊ _isDying (ΠΊΠ°ΠΊ ΠΎΠ±ΡΡΠ½ΠΎ) ΠΈ ΠΏΠΎΡΡΠ»Π°Π΅ΠΌ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ WM_FOLDER_CHANGE ΠΎΠΊΠ½Ρ, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΈΠΌΠ΅Π΅Ρ Π΄Π΅Π»ΠΎ Ρ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡΠΌΠΈ. ΠΡΠΎ β Π½Π΅ ΠΏΡΠ΅Π΄ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ Windows. ΠΠ½ΠΎ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΎ Π½Π°ΠΌΠΈ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡ ΠΎ ΠΏΠ°ΠΏΠΊΠ΅ ΠΎΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡΠΎΠΊΠ° Π΄ΡΡΠ³ΠΎΠΌΡ.
ΠΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π΅: ΡΠ΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΡΠΉ ΠΏΠΎΡΠΎΠΊ Π΄Π΅Π»Π°Π΅Ρ Π΄ΡΡΠ³ΠΎΠΉ Π²ΡΠ·ΠΎΠ² API, ΡΡΠΎΠ±Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡΡ ΡΠ°ΠΉΠ»ΠΎΠ²ΠΎΠΉ ΡΠΈΡΡΠ΅ΠΌΠ΅, ΡΠ·Π½Π°ΡΡ, ΡΡΠΎ ΠΎΠ½Π° Π½ΡΠΆΠ΄Π°Π΅ΡΡΡ Π² Π±ΠΎΠ»ΡΡΠ΅ΠΌ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π΅ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠΉ. ΠΠ°ΡΠ΅ΠΌ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ ΠΊ ΠΎΠΆΠΈΠ΄Π°ΡΡΠ΅ΠΌΡ ΠΏΠΎΡΠΎΠΊΡ, Π½Π°Ρ ΠΎΠ΄ΡΡΠ΅ΠΌΡΡΡ Π² ΡΠΎΡΡΠΎΡΠ½ΠΈΠΈ ΡΠ½Π°. ΠΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ Windows ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ Π½Π°ΡΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ WM_FOLDER_CHANGE ΠΈΠ· ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ ΠΈ ΠΏΠΎΡΡΠ»Π°Π΅Ρ Π΅Π³ΠΎ ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ ΠΏΡΠΎΡΠ΅Π΄ΡΡΠ΅ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡΠ΅Π³ΠΎ ΠΎΠΊΠ½Π°. ΠΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠΈ ΡΡΡΡ ΠΏΠΎΠ·ΠΆΠ΅.
UINT const WM_FOLDER_CHANGE = WM_USER;
void FolderWatcher::Loop() {
for (;;) {
// Wait for change notification
DWORD waitStatus = WaitForSingleObject(_notifySource, INFINITE);
if (WAIT_OBJECT_0 == waitStatus) {
// If folder changed
if (_isDying) return;
PostMessage(_hwndNotifySink, WM_FOLDER_CHANGE, 0, (LPARAM)_folder);
// Continue change notification
if (!_notifySource.ContinueNotification()) {
// Error: Continuation failed
return;
}
} else {
// Error: Wait failed
return;
}
}
}
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ, ΡΡΠΎ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ Π² ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ ΠΏΡΠΎΡΠ΅Π΄ΡΡΠ΅ Π² ΠΎΡΠ²Π΅Ρ Π½Π° Π½Π°ΡΠ΅ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅. ΠΡ Π²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΌΠ΅ΡΠΎΠ΄ ΠΠΎΠ½ΡΡΠΎΠ»Π»Π΅ΡΠ° OnFolderChange. ΠΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ Π΄Π΅Π»Π°ΡΡ Π²ΡΠ΅, ΡΡΠΎ ΠΌΡ Π·Π°Ρ ΠΎΡΠΈΠΌ. Π ΠΡΠΎΠ²ΠΎΠ΄Π½ΠΈΠΊΠ΅ (Explorer) ΠΎΠ½ ΡΠ΅Π³Π΅Π½Π΅ΡΠΈΡΡΠ΅Ρ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ³ΠΎ ΠΏΠ°ΠΏΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΡ ΠΌΡ Π½Π°Π±Π»ΡΠ΄Π°Π΅ΠΌ. Π Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΠΎΠ½ ΡΠΎΠ»ΡΠΊΠΎ Π²ΡΠ·ΡΠ²Π°Π΅Ρ ΠΏΡΠΎΡΡΠΎΠ΅ ΠΎΠΊΠ½ΠΎ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ. ΠΠ±ΡΠ°ΡΠΈΡΠ΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΡΡΠΎ ΠΌΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΠΌ ΠΈΠΌΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½Π½ΠΎΠΉ ΠΏΠ°ΠΏΠΊΠΈ ΠΊΠ°ΠΊ LPARAM. Π‘ΠΎΠ²Π΅ΡΡΠ΅Π½Π½ΠΎ Π½Π΅Π²Π°ΠΆΠ½ΠΎ, ΠΊΠ°ΠΊ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ WPARAM ΠΈ LPARAM, Π² ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΈ, ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌΠΎΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΌ.
ΠΠ΅ΠΆΠ΄Ρ ΠΏΡΠΎΡΠΈΠΌ, ΠΠ°Π±Π»ΡΠ΄Π°ΡΠ΅Π»Ρ ΠΠ°ΠΏΠΊΠΈ β ΡΠΎΠ»ΡΠΊΠΎ ΡΠ°ΡΡΡ ΠΠΎΠ½ΡΡΠΎΠ»Π»Π΅ΡΠ°.
case WM_FOLDER_CHANGE:
pCtrl->OnFolderChange(hwnd, (char const *)lParam);
return 0;
void Controller::OnFolderChange(HWND hwnd, char const * folder) {
MessageBox(hwnd, "Change Detected, "Folder Watcher", MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OK);
}
class Controller {
public:
Controller(HWND hwnd, CREATESTRUCT * pCreate);
~Controller();
void OnFolderChange(HWND hwnd, char const *folder);
private: