- •Процессы, нити и волокна
- •CrProces.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •Объекты синхронизации
- •Защита процесса от нереентрабельного кода
- •Описание функций управления процессами, нитями и волокнами
- •CreateEvent
- •CrEvent.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •CreateMutex
- •CrMutex.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •CreateSemaphore
- •CrSem.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •CreateThread
- •EnterCriticalSection
- •EntCrSec.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •ExitThread
- •InitializeCriticalSection
- •DeleteCriticalSection
- •LeaveCriticalSection
- •OpenSemaphore
- •TryEnterCriticalSection
- •WaitForMultipleObjects
CreateSemaphore
Описание Функция CreateSemaphore создает поименованный или безымянный объект семафора. Семафор, в котором для синхронизации используется счетчик, устанавливается в сигнальное состояние, когда значение счетчика в нем оказывается больше нуля, и в несигнальное состояние при достижении счетчиком нуля. Всякий раз когда семафор выбирается (например, с помощью WaitForSingleObject), счетчик в семафоре уменьшается. Каждый раз когда семафор освобождается с использованием функции Release-Semaphore, счетчик в семафоре увеличивается. Счетчик не может быть меньше нуля или больше значения, определяемого параметром ISemMax-Count.
Синтаксис DWORD CreateSemaphore(LPSECURITY_ATTRIBUTES lpThreadSecurity, LONG lSemInitialCount, LONG lSemMaxCount, LPCTSTR lpszSemName)
Включаемый файл winbase.h
См. также CloseHandle, DuplicateHandle, OpenSemaphore, ReleaseSemaphore, WaitForSingleObject, WaitForMultipleObjects.
Пример В приведенном ниже примере семафоры применяются для предоставления возможности выполнения процедуры порожденной нити только четырем нитям. Когда пользователь выбирает пункт меню Test!, создается новая нить. Процедура этой нити сначала пытается получить семафор с максимальным значением счетчика, равным четырем, выполняя цикл до тех пор, пока эта операция не завершится успешно. Независимо от того, сколько раз выбирается пункт меню Test!, защищенный код позволит одновременно выполняться только четырем нитям.
CrSem.h
#define IDM_EXIT 100
#define IDM_TEST 200
#define IDM_ABOUT 301
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
CrSem.rc
#include "windows.h"
#include "CrSem.h"
MYAPP ICON DISCARDABLE "GENERIC.ICO"
MYAPP MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
MENUITEM "&Test!", IDM_TEST
POPUP "&Help"
BEGIN
MENUITEM "&About My Application...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 171, 43
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
CAPTION "My Application"
FONT 8, "MS Sans Serif"
{
CONTROL "MyApp", -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 3, 2, 16, 16
CONTROL "Generic Application", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 4, 100, 8
CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 116, 26, 50, 14
}
CrSem.C
#include <windows.h>
#include "CrSem.h"
HINSTANCE hInst; // current instance
LPCTSTR lpszAppName = "MyApp";
LPCTSTR lpszTitle = "My Application";
Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
// Register the main application window class.
//............................................
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, lpszAppName );
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage( hInstance, lpszAppName,
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR );
if ( !RegisterClassEx( &wc ) )
return( FALSE );
hInst = hInstance;
// Create the main application window.
//....................................
hWnd = CreateWindow( lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if ( !hWnd )
return( FALSE );
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
while( GetMessage( &msg, NULL, 0, 0) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return( msg.wParam );
}
LPCTSTR lpszSemaphore = "Test Semaphore";
// This is a child thread procedure that waits for a semaphore,
// holds the semaphore for five seconds, and releases the semaphore.
// Threads that cannot get semaphores will wait until other threads exit.
//.......................................................................
DWORD WINAPI ChildThreadProc( LPDWORD lpData )
{
TCHAR szBuffer[256];
DWORD dwSemCount = 0;
HWND hList = (HWND)lpData;
HANDLE hSemaphore = OpenSemaphore( SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, lpszSemaphore );
wsprintf( szBuffer,"Thread %x waiting for semaphore %x",
GetCurrentThreadId(), hSemaphore );
SendMessage( hList, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuffer );
// Check for signaled semaphore.
//..............................
WaitForSingleObject( hSemaphore, INFINITE );
wsprintf( szBuffer,"Thread %x got semaphore", GetCurrentThreadId() );
SendMessage( hList, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuffer );
Sleep( 5000 );
// Release semaphore.
//...................
ReleaseSemaphore( hSemaphore, 1, &dwSemCount );
wsprintf( szBuffer,"Thread %x is done with semaphore. Its count was %ld.",
GetCurrentThreadId(), dwSemCount );
SendMessage( hList, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuffer );
CloseHandle( hSemaphore );
return( 0 );
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
static HWND hList = NULL;
static HANDLE hSemaphore = NULL;
switch( uMsg )
{
case WM_CREATE:
// Create list box.
//.................
hList = CreateWindowEx( WS_EX_CLIENTEDGE, "LISTBOX", "",
LBS_STANDARD | LBS_NOINTEGRALHEIGHT |
WS_CHILD | WS_VISIBLE,
0, 0, 10, 10,
hWnd, (HMENU)101,
hInst, NULL );
hSemaphore = CreateSemaphore( NULL, 4, 4, lpszSemaphore );
break;
case WM_SIZE :
if ( wParam != SIZE_MINIMIZED )
MoveWindow( hList, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
break;
case WM_COMMAND :
switch( LOWORD( wParam ) )
{
case IDM_TEST:
{
DWORD dwChildId;
CreateThread( NULL, 0, ChildThreadProc, hList, 0, &dwChildId );
}
break;
case IDM_ABOUT :
DialogBox( hInst, "AboutBox", hWnd, (DLGPROC)About );
break;
case IDM_EXIT :
DestroyWindow( hWnd );
break;
}
break;
case WM_DESTROY :
if ( hSemaphore )
CloseHandle( hSemaphore );
PostQuitMessage(0);
break;
default :
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) );
}
return( 0L );
}
LRESULT CALLBACK About( HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if ( LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}