Ово је мој следећи тестни пројекат да видим која би библиотека за обраду датотека за Делпхи најбоље одговарала за мој задатак „скенирања датотека“ који бих желео да обрадим у више нити / у низу нити.
Да поновим свој циљ: трансформишите моје секвенцијално „скенирање датотека“ од 500-2000 + датотека из приступа без навоја у један са навојем. Не бих требао да покрећем 500 нити истовремено, желео бих да користим низ нити. Повез навоја је класа налик на ред која садржи бројне покренуте нити са сљедећим задатком из реда чекања.
Први (врло основни) покушај је направљен једноставним проширењем ТТхреад класе и имплементацијом методе Екецуте (мој парни стринг парсер).
Пошто Делпхи нема класу полагања нити која је имплементирана ван оквира, у другом покушају покушао сам користећи ОмниТхреадЛибрари Примоза Габријелчића.
ОТЛ је фантастичан, има милион начина за извршавање задатка у позадини, начин на који желите да имате приступ „ватри и заборави“ за предавање навођених извршења делова вашег кода.
АсинцЦаллс Андреас Хаусладен
Напомена: Следеће би било лакше пратити ако прво преузмете изворни код.
Док сам истраживао више начина да се неке од мојих функција извршавају на навојни начин, одлучио сам да испробам и јединицу "АсинцЦаллс.пас" коју је развио Андреас Хаусладен. Анди'с АсинцЦаллс - Асинхрони позиви функција јединица је још једна библиотека коју Делпхи програмер може користити да олакша бол при имплементацији навојаног приступа у извршавању неког кода.
Са Андијевог блога: Помоћу АсинцЦаллс можете истовремено да извршавате више функција и синхронизујете их у свакој тачки у функцији или методи која их је покренула... АсинцЦаллс јединица нуди разне прототипе функција за позивање асинхроних функција... Имплементира низ нити! Инсталација је супер једноставна: само користите асинццалл из било које јединице и имате тренутни приступ стварима као што су "извршавање у засебном низу, синхронизовање главног корисничког сучеља, причекајте док не завршите".
Поред слободног коришћења (МПЛ лиценца) АсинцЦаллс, Анди често објављује и сопствене поправке за Делпхи ИДЕ попут „Делпхи убрзава" и "ДДевЕктенсионс„Сигуран сам да сте чули (ако већ не користите).
АсинцЦаллс у акцији
У суштини, све функције АсинцЦалл враћају ИАсинцЦалл интерфејс који омогућава синхронизацију функција. ИАсницЦалл излаже следеће методе:
//в 2,98 од асинццаллс.пас
ИАсинцЦалл = интерфејс
// чека док се функција заврши и врати повратну вриједност
функција Синц: Интегер;
// враћа Труе кад је функција асинкроне завршена
функција завршена: Боолеан;
// враћа повратну вриједност функције асинхроне, када је Финисхед ТРУЕ
функција РетурнВалуе: Интегер;
// каже АсинцЦаллс да се додељена функција не сме извршити у тренутној претњи
поступак ФорцеДифферентТхреад;
крај;
Ево примера позива методе која очекује два цела параметра (враћање ИАсинцЦалл):
ТАсинцЦаллс. Инвоке (АсинцМетход, и, Рандом (500));
функција ТАсинцЦаллсФорм. АсинцМетход (таскНр, слеепТиме: интегер): цели број;
започети
резултат: = време спавања;
Слееп (време спавања);
ТАсинцЦаллс. ВЦЛИнвоке (
процедура
започети
Пријавите се (Формат ('завршено> нр:% д / задатци:% д / спавао:% д', [таскнр, асинцХелпер). ТаскЦоунт, слеепТиме]));
крај);
крај;
ТАсинцЦаллс. ВЦЛИнвоке је начин за синхронизацију са вашим главним нитом (главна нит апликације - корисничко сучеље ваше апликације). ВЦЛИнвоке се одмах враћа. Анонимна метода ће се извршити у главној нити. Ту је и ВЦЛСинц који се враћа када је анонимна метода позвана у главну нит.
Навојни низ у АсинцЦаллс
Вратите се мом задатку "скенирања датотека": приликом храњења (у петљи) асфалтни низ нит асинццаллс са низом ТАсинцЦаллс. Позовите () позиве, задаци ће се додати у интерни базен и извршават ће се „када дође вријеме“ (када су претходно додани позиви завршени).
Причекајте да се сви ИАсинцЦаллс заврше
АсинцМултиСинц функција дефинисана у асниццаллс чека да се асинц позиви (и други ручки) заврше. Има их неколико преоптерећен начина за позивање АсинцМултиСинц, а ево најједноставнијег:
функција АсинцМултиСинц (цонст Листа: низ ИАсинцЦалл; ВаитАлл: Боолеан = Тачно; Милисекунде: Кардинал = ИНФИНИТЕ): Кардинал;
Ако желим да се "причека све" имплементира, морам да испуним низ ИАсинцЦалл и направим АсинцМултиСинц у одељцима од 61.
Мој АсницЦаллс помагач
Ево дела ТАсинцЦаллсХелпер-а:
УПОЗОРЕЊЕ: делимични код! (пуни код доступан за преузимање)
користи АсинцЦаллс;
тип
ТИАсинцЦаллАрраи = низ ИАсинцЦалл;
ТИАсинцЦаллАрраис = низ ТИАсинцЦаллАрраи;
ТАсинцЦаллсХелпер = класа
приватни
фЗадаци: ТИАсинцЦаллАрраис;
својство Задаци: ТИАсинцЦаллАрраис читати фТаскс;
јавни
процедура АддТаск (цонст позив: ИАсинцЦалл);
процедура ВаитАлл;
крај;
УПОЗОРЕЊЕ: делимични код!
процедура ТАсинцЦаллсХелпер. ВаитАлл;
вар
и: цели број;
започети
за и: = високо (задаци) до Низак (задаци) урадити
започети
АсинцЦаллс. АсинцМултиСинц (Задаци [и]);
крај;
крај;
На овај начин могу „чекати све“ у комадима од 61 (МАКСИМУМ_АСИНЦ_ВАИТ_ОБЈЕЦТС) - тј. Чекајући низ ИАсинцЦалл.
С горе наведеним, мој главни код за пуњење нити изгледа овако:
процедура ТАсинцЦаллсФорм.бтнАддТасксЦлицк (Пошиљалац: ТОбјецт);
цонст
нрИтемс = 200;
вар
и: цели број;
започети
асинцХелпер. МакТхреадс: = 2 * Систем. ЦПУЦоунт;
ЦлеарЛог ('започиње');
за и: = 1 до нрИтемс урадити
започети
асинцХелпер. АддТаск (ТАсинцЦаллс). Инвоке (АсинцМетход, и, Рандом (500));
крај;
Пријавите се ('све у');
// сачекајте све
//asyncHelper.WaitAll;
// или дозволите отказивање свега што није почело кликом на дугме "Откажи све":
док НЕ асинцХелпер. Све завршено урадити Апликација. ПроцессМессагес;
Пријавите се ('завршено');
крај;
Отказати све? - Морате да промените АсинцЦаллс.пас :(
Такође бих желео да „откажем“ оне задатке који се налазе у базену, али чекају на њихово извршавање.
Нажалост, АсинцЦаллс.пас не пружа једноставан начин отказивања задатка након што је додан у низ нити. Не постоји ИАсинцЦалл. Откажи или ИАсинцЦалл. ДонтДоИфНотАлреадиЕкецутинг или ИАсинцЦалл. Немој обратити пажњу на мене.
Да би ово функционисало, морао сам да променим АсинцЦаллс.пас покушавајући да га изменим што је мање могуће - тако да кад Анди изда нову верзију, морам додати само неколико редака да бих имао идеју "Откажи задатак" рад.
Ево шта сам урадио: Додао сам „поступак отказивања“ у ИАсинцЦалл. Процедура за одустајање поставља поље "ФЦанцеглед" (додано) које се проверава када се базен спрема да изврши задатак. Требао сам мало изменити ИАсинцЦалл. Завршено (тако да се извештаји о позивима завршавају чак и када су отказани) и ТАсинцЦалл. ИнтернЕкецутеАсинцЦалл поступак (не извршава позив ако је отказан).
Можете користити ВинМерге да се лако пронађу разлике између Андијевог оригиналног асинццалл.пас-а и моје измењене верзије (укључено у преузимању).
Можете преузети пуни изворни код и истражити.
Исповест
ОБЈАВА! :)
Тхе Откажи позив метода спречава позивање АсинцЦалл-а. Ако је АсинцЦалл већ обрађен, позив на ЦанцелИнвоцатион нема ефекта и функција Отказани ће вратити Фалсе јер АсинцЦалл није отказан.
Тхе Отказано враћа методу Труе ако је АсинцЦалл отказао ЦанцелИнвоцатион.
Тхе Заборави метода уклања везу интерфејса ИАсинцЦалл од интерног АсинцЦалл. То значи да ако нестане последња референца на ИАсинцЦалл интерфејс, асинхрони позив ће се и даље извршити. Методе интерфејса ће изузети изузетак ако се позове након позива Форгет. Асинц функција не смије улазити у главни нит јер се може извршити након ТТхреад-а. Механизам за синхронизацију / ред чекања је искључио РТЛ што може довести до мртве браве.
Имајте на уму да ипак можете имати користи од мог АсинцЦаллсХелпер-а ако требате сачекати да се сви позиви асинц-а заврше са „асинцХелпер. ВаитАлл "; или ако требате „ЦанцелАлл“.