Пример за най-простата многонишкова програма WinAPI, Бележки на програмиста

Пример за най-простата многонишкова програма WinAPI

Продължаваме да припомняме Windows API. Досега сме писали тъжни и скучни еднонишкови програми от поредицата „извикайте правилната процедура с необходимите аргументи и разгледайте нейния код за връщане“. Днес най-накрая ще напишем, макар и проста, но все пак същата многонишкова програма, с едни и същи нишки и мютекси, които всички постоянно се карат.

От новите процедури се нуждаем от следното.

Както се досещате, CreateThread създава нова нишка. Аргументи отляво надясно - (1) нещо, за което не е необходимо да знаете сега, (2) размер на стека в байтове, закръглен до размер на страницата, ако е нула, тогава се взема размерът по подразбиране, (3) указател към процедурата, от която да започне нишката за изпълнение, (4) аргументът на процедурата, предадена от предишния аргумент, обикновено се предава указател към някаква структура, (5) флагове, например, можете да създадете спряна нишка (CREATE_SUSPENDED) и след това го стартирайте с помощта на ResumeThread, (6), където да напишете ThreadId на създадения поток. Ако е успешна, процедурата връща манипулатора на създадения поток. В случай на грешка се връща NULL и подробностите могат да бъдат намерени чрез GetLastError.

CreateMutex създава нов мютекс. Не е нужно да знаете за първия аргумент сега. Ако вторият аргумент е TRUE, създаденият мютекс веднага ще бъде заключен от текущата нишка, ако вторият аргумент е FALSE, се създава отключен мютекс. Третият аргумент е името на мютекса, ако искаме да създадем именован мютекс. Все още не ни трябват именовани мютекси, така че преминаваме NULL. Връщаните стойности са точно същите като CreateThread.

WaitForSingleObject изчаква обектът, чийто манипулатор е предаден като първия аргумент, да влезе в сигнализирано състояние. Освен това, в зависимост от вида на обекта, процедурата може да промени състоянието си. WaitForSingleObject може да се приложи към мютекси, семафори, нишки, процеси и други. Ако hHandle е манипулатор на мютекс, процедурата изчаква мутексът да се освободи и след това го заключва. Ако hHandle е манипулатор на поток, тогава процедурата просто чака да завърши. Вторият аргумент определя времето за изчакване в милисекунди. Можете да чакате вечно, като въведете специалната стойност INFINITE. Ако посочите нула, процедурата не преминава в режим на заспиване, а се връща незабавно.

В случай на грешка процедурата връща WAIT_FAILED и GetLastError ще ви помогне да разберете подробностите. При успех се връща WAIT_OBJECT_0, ако изчакахме обектът да премине в състояние на сигнала и WAIT_TIMEOUT, ако изтече времето за изчакване. Също така можем да получим WAIT_ABANDONED. Това се случва, ако нишката, която държи мютекса, е прекратена, без да я освободи. В този случай мютексът се заключва от текущата нишка, но целостта на данните, достъпът до които е бил ограничен от мютекса, по очевидни причини е под въпрос.

WaitForMultipleObjects работи като WaitForSingleObject, но за масив от обекти. Първият аргумент указва размера на масива, трябва да бъде строго по-голям от нула и да не надвишава MAXIMUM_WAIT_OBJECTS (което е точно 64). Вторият аргумент е указател към масив от манипулатори. Масивът може да съдържа манипулатори на обекти от различни типове, но многократното включване на един и същ манипулатор се счита за грешка. Ако третият аргумент е ИСТИНА, процедурата изчаква преминаването в състояние на сигнала на всички обекти, в противен случай - за някой от посочените обекти. Семантиката на последния аргумент е точно същата, както в случая на WaitForSingleObject.