Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метода Процессы и потоки.doc
Скачиваний:
7
Добавлен:
14.07.2019
Размер:
401.92 Кб
Скачать

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);

}