ПредишенСледващото

При стартиране на приложението, системата автоматично създава нишка, за да го изпълни. Ето защо, ако един-единствен резба приложение, целият код, ще се изпълнява последователно, като се вземат предвид всички условни и безусловни скокове.

Multithreading осигурява псевдо работа на няколко програми. В някои случаи, без създаването на нишки не може да бъде избегнато, например, когато се работи с гнезда в блокиращ режим.

В Делфи има специален клас, който реализира потока - tthread. Това е най-базовия клас, от които е необходимо да се наследи класа и замени метода на изпълнение.

Сега можете да напишете кода, изпълнението на които ще бъдат окачени в тялото на процедурата по програма tnew.execute.

Fine точка. Тялото на процедурата не е необходимо да се обадите на изпълни метод прародител.

Сега трябва да се започне конец. Като всеки клас tnew трябва да създадете:

Стойност вярно в метода за създаване на означава, че след създаването на потока на курса няма да се стартира автоматично.

След това да означава, че след като код поток, след като тя е завършена, т.е. Не е нужно да се притеснявате за неговото закриване. В противен случай, трябва да се обадите на функцията за прекратяване.

Ние задаване на приоритета на една от възможните стойности:

tpidle работи, когато системата не се използва
Най-ниската tplowest
tplower Ниска
tpnormal Нормално
висока tphigher
най-висока tphighest
tptimecritical критична

Аз препоръчвам да не твърде висок приоритет, тъй като поток може значително да се зареди системата.

Fine точка. Ако поток присъства безкраен цикъл нищо, системата поток ще се зареди очните ябълки. За да избегнете това, поставете сън функция (н), където п - броят на милисекунди, че потокът ще спре неговото изпълнение, се срещна тази функция. н трябва да се избира в зависимост от задачата.

Между другото, ако имате намерение да пишете код потока за всеки отделен модул, тя може да бъде малко по-лесно да се напише клас скелет. За да направите това, изберете магазина обект - нишка обект (Това е нов раздел). То се появява прозорец, в който можете да въведете името на класа, а след това щракнете върху OK, новият модул автоматично създава скелета на вашата класа.


синхронизация Тема при достъп на VCL-компоненти

Така че сме се научили да се създаде нишки. Но има появи нещо интересно: какво би станало, ако двете теми имат достъп до едни и същи данни в справката? Например, две теми се опита да промени заглавието на основната форма.

Специално за тази операционна система се прилагат механизми за синхронизиране. По-специално, в tthread в класната стая има метод, който позволява да се избегне едновременното достъп до VCL-компоненти:

процедура синхронизиране (метод: tthreadmethod);

Тук е пълен пример, в който addstr метод добавя няколко линии в бележката. Ако ние просто се обадете на метод, ще бъдат добавени линиите на потока в произволен ред. Ако позоваването на метод addstr синхронизиране, след първите редове се добавят по един поток и след това втората. Оказва се, че потокът изключително улавя бележка ресурс и добавя необходимата информация, след добавяне на косъм пресата бележката, а сега имам друг поток може да се добавя към бележката вашите данни. По-малко думи - повече LAS:

употреби
прозорци, съобщения, sysutils, варианти, класове, графики, управление, форма и, диалогови прозорци, stdctrls;

tnew = клас (tthread)
частен
ите: низ;
процедура addstr;
защитени
Процедура за изпълнение; отменят;
приключи;

Var
форма 1: TForm 1;
new1, new2: tnew;

процедура TForm 1.button1click (подател: TObject);
започвам
new1: = tnew.create (истина);
new1.freeonterminate: = вярно;
new1.s: = '1 нишка;
new1.priority: = tplowest;
new2: = tnew.create (истина);
new2.freeonterminate: = вярно;
new2.s: = '2 нишка;
new2.priority: = tptimecritical;
new1.resume;
new2.resume;
приключи;

процедура tnew.execute;
започвам
синхронизиране (addstr); // разговори синхронизацията
// addstr; // метод Call без синхронизация
приключи;

Други методи за синхронизация. модулни syncobjs

В syncobjs модул за синхронизация са класове, които се увиват разговори през API функции. Като цяло, този модул обяви пет класа. tcriticalsection, tevent, както и по-прост клас изпълнение tevent - tsimpleevent и се използва за синхронизиране на конци, а останалите класове не могат да се видят. Тук е йерархията на класовете в този модул:

Критични участъци tcriticalsection

Най-простият е да се разбере tcriticalsection или критична точка. Кодът намира в критична точка, може да се извърши само с една нишка. По принцип всеки код, ако не е освободена, и се влиза през критичния участък на код. В началото кодът е вход в раздела функция и да завърши своя изходящ от секцията. Ако част е заета от друга нишка, в очакване на критичния участък нишката не е освободена.


В началото на критична точка, трябва да създадете:


Var
раздел: tcriticalsection; // глобална променлива
започвам
section.create;
приключи;

Предполагаме, че е функция, при които добавянето на елементи в глобалната масива:

Да предположим, че функцията се нарича множество потоци, така че не съществува конфликт, критичната точка може да се използва в съответствие със следния начин:

функция addelem (I: число);
Var
п: цяло число;
започвам
section.enter;
п: = дължина (УО);
SetLength (УО, п + 1);
Мас [М + 1]: = I;
section.leave;
приключи;

Уточнява, че критичните участъци могат да бъдат няколко. Ето защо, когато се използват няколко функции, които могат да бъдат конфликти според нуждата им да се създаде критична точка за всяка функция. След края на тяхното използване, функциите, вече няма да се нарича, раздел трябва да бъде унищожен.

Както разбирате, много се надявам, че входа и изхода от критичната точка не трябва да бъдат в една и съща функция. Вход означава само, че друга нишка се натъкват на входа и е установено, служебните си задължения, е спряно. Добив от просто освобождава входа. Много просто, критичната точка може да се представи под формата на тясна тръба на един поток, веднага след като потокът подходи тунела, той я гледа, и ако той вижда, че през тръбата вече някой се изкачва, ще изчака, докато другият не излезе.

Ето един пример, при който елементът на прибавяне в динамичен масив. Функцията Sleep добавя забавяне на цикъла, който позволява да се види ясно на конфликта от данните, ако, разбира се, извадете си влизане и излизане от критичната точка в кода.

употреби
прозорци, съобщения sysutils, варианти, класове, графики, управление, форма ите, диалогови прозорци, stdctrls, syncobjs;

тип
TForm 1 = клас (TForm)
button1: tbutton;
Memo1: tmemo;
форма процедура се създаде (подател: TObject);
форма процедура унищожи (подател: TObject);
процедура button1click (подател: TObject);
частен

обществен

приключи;

tnew = клас (tthread)
защитени
Процедура за изпълнение; отменят;
приключи;

Var
форма 1: TForm 1;
CS: tcriticalsection;
new1, new2: tnew;
Мас: масив от цяло число;

процедура TForm 1.form създаде (подател: TObject);
започвам
SetLength (УО, 1);
Мас [0] =: 6;
// Създаване на критична точка
CS: = tcriticalsection.create;
приключи;

процедура TForm 1.form унищожи (подател: TObject);
започвам
// Изтриване на критична точка
cs.free;
приключи;

процедура TForm 1.button1click (подател: TObject);
започвам
new1: = tnew.create (истина);
new1.freeonterminate: = вярно;
new1.priority: = tpidle;
new2: = tnew.create (истина);
new2.freeonterminate: = вярно;
new2.priority: = tptimecritical;
new1.resume;
new2.resume;
приключи;

За да започнете с не много изчакване функции. Тази функция, която спира нишката. Това е специфичен случай изчакване функция сън, се предава като аргумент на броя милисекунди, че се изисква замразяване или пауза потока.

Fine точка. Ако се обадите на сън (0), потокът ще се откажат от инсулт му - процесорно време и след това да се изправи на опашката готов да изпълни.

Изчакайте-пълните функции описания като параметри предава поток (и). Няма да се спирам на тях сега в подробности. По принцип, да изчакат-функции оформят някои класове изрично синхронизация, останали в която не е изрично.

Събития tevent се използват не само в многонишков приложение, но също и в единични резбовани като координация между секцията на кода и данните от едно приложение на друго. В многонишкови приложения използване tevent изглежда по-разумно и разбираемо.

Всичко се случва по следния начин. Ако събитие е зададен, можете да продължите да работите, ако събитието е изчистено, всички други теми, които ви очакват. Разликата между събитията и критичните участъци с това, че събитията се проверяват в кода на потока и се използва изчакване функция изрично. Ако критичната точка за изчакване-функцията се извършва автоматично, като се използва събитието, трябва да го наречем за замразяване на потока.

Събитията са автоматично нулиране без автоматично нулиране. С автоматично нулиране това означава, че веднага след завръщането си от събитие изчакат функция е сменена с нова. Ако използвате събития без да е необходимо за автоматично нулиране, като ги възстановите.

Събитие без автоматично нулиране удобен пауза във всяка отделна част от потока на код. Просто спрете потока, където няма значение къде се случва, измръзване, можете да използвате tthread.suspend метод. Събития автоматично нулиране е възможно да се използват, както и критични участъци.

За да започнете, трябва да създадете на събитието и за предпочитане пред потоците са създадени да ги използват, въпреки че по-прецизно да се обадя чакам-функция.

създадете (eventattributes: psecurityattributes; manualreset, initialstate: Булева; Конст име: низ);

eventattributes - нула вземат.
manualreset - Авто нулиране - фалшиви, без автоматично нулиране - вярно.
initialstate - първоначалното състояние на истина - фиксирани, невярна - освободен.
Конст име - името на събитието, поставете празен. Име на събитието е необходимо, при обмена на данни между процеси.

Var
събитие: tevent;
new1, new2: tnew; // потоци
...
започвам
събитие: = tevent.create (нула, неверни, фалшиви " ');
приключи;
процедура tnew.execute;
Var
п: цяло число;
започвам
event.waitfor (безкраен);
п: = дължина (УО);
SetLength (УО, п + 1);
Мас [М + 1]: = I;
event.setevent;
приключи;

Сега всичко, което не е грешка.

По-лесно е да се използва tsimpleevent клас, който е наследник tevent и се различава от него само с това, че му конструктор призовава строителя родител веднъж зададените параметри:

създадете (нула, вярно, невярно, '');

В действителност, има едно събитие без TSimpleEvent автоматично нулиране с държавно наново, а без име.

Следният пример показва как да се спре изпълнението на потока в определено място. В този пример, има три форма progressbar, поток изпълва progressbar. Ако желаете, можете да спрете и да се започне попълване progressbar. Както сте разбрали, ние ще създадем едно събитие без автоматично нулиране. Въпреки, че е подходящо да се използва tsimpleevent, ние използвахме tevent, защото да се научат да работят с tevent просто ще продължи tsimpleevent.

употреби
прозорци, съобщения sysutils, варианти, класове, графики, управление, форма ите, диалогови прозорци, stdctrls, syncobjs, comctrls;

тип
TForm 1 = клас (TForm)
button1: tbutton;
progressbar1: tprogressbar;
progressbar2: tprogressbar;
progressbar3: tprogressbar;
BUTTON2: tbutton;
форма процедура се създаде (подател: TObject);
форма процедура унищожи (подател: TObject);
процедура button1click (подател: TObject);
процедура button2click (подател: TObject);
частен

обществен

приключи;

tnew = клас (tthread)
защитени
Процедура за изпълнение; отменят;
приключи;

Var
форма 1: TForm 1;
ново: tnew;
събитие: tevent;

процедура TForm 1.form създаде (подател: TObject);
започвам
// Създаване на събитие, преди да го използвате
събитие: = tevent.create (нула, вярно, вярно, '');
// Започнете поток
нов: = tnew.create (истина);
new.freeonterminate: = вярно;
new.priority: = tplowest;
new.resume;
приключи;

процедура TForm 1.form унищожи (подател: TObject);
започвам
// Изтриване на събитието
event.free;
приключи;


процедура tnew.execute;
Var
п: цяло число;
започвам
п: = 0;
докато истинската задачи
започвам
// изчакване функция
event.waitfor (безкраен);
ако п> 99 след това
п: = 0;
// В същото време увеличените
форма 1.progressbar1.position: = N;
форма 1.progressbar2.position: = N;
форма 1.progressbar3.position: = N;
// забавяне за видимост
сън (100);
Inc (п)
приключи;
приключи;

процедура TForm 1.button1click (подател: TObject);
започвам
// Задаване на събитието
// изчакване функция ще fozvraschat контрол веднага
event.setevent;
приключи;

процедура TForm 1.button2click (подател: TObject);
започвам
// изчакване функционални блокове кода на конеца
event.resetevent;
приключи;


Пример за използване на събития автоматично нулиране е работата на двата потока, и те работят по следния начин. Една нишка подготвя данните и друга тема, след като данните са пълни, добре, например, ги изпраща на сървъра, или някъде другаде. Оказва се, един вид алтернативна работа.

употреби
прозорци, съобщения sysutils, варианти, класове, графики, управление, форма ите, диалогови прозорци, stdctrls, syncobjs, comctrls;

tproc = клас (tthread)
защитени
Процедура за изпълнение; отменят;
приключи;

tsend = клас (tthread)
защитени
Процедура за изпълнение; отменят;
приключи;

Var
форма 1: TForm 1;
Proc: tproc;
изпрати: tsend;
събитие: tevent;

процедура TForm 1.form създаде (подател: TObject);
започвам
// Създаване на събитие, преди да го използвате
събитие: = tevent.create (нула, невярно, вярно, '');
// започне нишката
Proc: = tproc.create (истина);
proc.freeonterminate: = вярно;
proc.priority: = tplowest;
proc.resume;
изпрати: = tsend. създаде (истина);
изпратите. freeonterminate: = вярно;
изпратите. приоритет: = tplowest;
изпратите. възобновяване;
приключи;

процедура TForm 1.form унищожи (подател: TObject);
започвам
// Изтриване на събитието
event.free;
приключи;

Това е синхронизация модул всички обекти syncobjs, което по принцип е достатъчно за решаване на различни проблеми. В прозорци има и други предмети за синхронизация, които също могат да бъдат използвани в Делфи, но на ниво API. Това мутекс - мутекс, семафор - семафор и очакваните таймери.

Подкрепете проекта - споделете линка, благодаря!