Suspend на TIdPeerThread, IdHTTPServer, D7/Indy9
16 отговора
0 прегледа
Suspend на TIdPeerThread, IdHTTPServer, D7/Indy9
Suspend на TIdPeerThread, IdHTTPServer, D7/Indy9.
Впрочем, да опиша по-подробно проблема:
Пиша веб сървър на D7 и Indy9.
Не мога да намеря информация, за да схвана логиката на ползване на TIdPeerThread. Мога да се опитам да ги ползвам като обикновенни нишки (те са наследници, през няколко поколения, на TThread). Обаче гледам, че има маса пропъртита за управление на временното спиране на тия нишки.
Чета и ползвам хелпа на Инди 9, Indy in Depth (дълбочините на Indy - много повърхностна книга), както и Indy9Demos_26Oct04.
По-подробно:
Налага се част от данните, които сървърът предоставя, самият той да ги взема от друго приложение.
Та проблемът ми е, че интерфейсът с другото приложение трябва да се синхронизира и да се изчака връщането на резултата, преди нишката на сървъра да продължи (т.е. нишката на конкретната заявка - всяка заявка си е в нишка).
Т.е. налага се да спра нишката на IndiHTTP сървъра, да изпратя заявка до другото приложение, да стане събитието за отговор на завската и с тоя отговор нишката на IndiHTTP сървъра да продължи нататък.
Та, моля разбирачите на Indy да ми помогнат!
ПП
В събитието, което получава заявката и подготвя отговора:
{}procedure TIdHTTP_Server.IdHTTPServerCommandGet( AThread: TIdPeerThread; aRequestInfo: TIdHTTPRequestInfo; aResponseInfo: TIdHTTPResponseInfo);
се предава една нишка: AThread: TIdPeerThread.
Как се ползва тая нишка - няма никъде описано.
Аз мога да приложа и дървената хватка - да си седя в обработчика на събитието, докато ми дойде кефа и данните, ама не ги обичам тия работи, да го е!
Впрочем, да опиша по-подробно проблема:
Пиша веб сървър на D7 и Indy9.
Не мога да намеря информация, за да схвана логиката на ползване на TIdPeerThread. Мога да се опитам да ги ползвам като обикновенни нишки (те са наследници, през няколко поколения, на TThread). Обаче гледам, че има маса пропъртита за управление на временното спиране на тия нишки.
Чета и ползвам хелпа на Инди 9, Indy in Depth (дълбочините на Indy - много повърхностна книга), както и Indy9Demos_26Oct04.
По-подробно:
Налага се част от данните, които сървърът предоставя, самият той да ги взема от друго приложение.
Та проблемът ми е, че интерфейсът с другото приложение трябва да се синхронизира и да се изчака връщането на резултата, преди нишката на сървъра да продължи (т.е. нишката на конкретната заявка - всяка заявка си е в нишка).
Т.е. налага се да спра нишката на IndiHTTP сървъра, да изпратя заявка до другото приложение, да стане събитието за отговор на завската и с тоя отговор нишката на IndiHTTP сървъра да продължи нататък.
Та, моля разбирачите на Indy да ми помогнат!
ПП
В събитието, което получава заявката и подготвя отговора:
{}procedure TIdHTTP_Server.IdHTTPServerCommandGet( AThread: TIdPeerThread; aRequestInfo: TIdHTTPRequestInfo; aResponseInfo: TIdHTTPResponseInfo);
се предава една нишка: AThread: TIdPeerThread.
Как се ползва тая нишка - няма никъде описано.
Аз мога да приложа и дървената хватка - да си седя в обработчика на събитието, докато ми дойде кефа и данните, ама не ги обичам тия работи, да го е!
Редактирано от NikB на
Re: Suspend на TIdPeerThread, IdHTTPServer, D7/Indy9
Не би трябвало да излизаш от обработчика на събитието. Suspend няма да ти свърши работа, защото няма как (откъде) после да си събудиш нишката. Най-добре за синхронизацията да ползваш мутекси (или нещо подобно) и WaitForSingleObject. Или пък да си викаш Sleep в цикъл докато дойдат данните от другото приложение.
Всъщност почти съм сигурен, че ако излезеш от процедурата indy-то (почти) веднага ще те викне пак. Но тогава ти се усложнява логиката в обработчика - трябва ли да четеш от клиента, не трябва ли... Много по-просто ще е да не излизаш.
ПП Не бях обърнал внимание кой точно ти е евента. Това, за което говорех е по-валидно за OnExecute. При теб евента ще ти се викне пак чак при следващата заявка, така че не трябва да излизаш от него.
Всъщност почти съм сигурен, че ако излезеш от процедурата indy-то (почти) веднага ще те викне пак. Но тогава ти се усложнява логиката в обработчика - трябва ли да четеш от клиента, не трябва ли... Много по-просто ще е да не излизаш.
ПП Не бях обърнал внимание кой точно ти е евента. Това, за което говорех е по-валидно за OnExecute. При теб евента ще ти се викне пак чак при следващата заявка, така че не трябва да излизаш от него.
Редактирано от andrew_nikoloff на
OK
Благодаря ти.
И аз се ориентирах към нещо подобно, но е много по-добре с компетентен съвет :)
В началото, като четох сорсовете на Инди нишките, реших, че може да се работи с тяхното събитие OnStop (или OnStoping ли беше?) и си мислех, че това е механизъм да спра подходящо нишката, да си свърша работата и да продължа нишката.
Може и да има такава хватка, ама не я разбрах как става.
Разликата, с това, което предлагаш не е голяма и дори, ако има такъв механизъм в Инди, той ми се струва излишен (сложили са го за "стил").
Благодаря ти още веднъж!
И аз се ориентирах към нещо подобно, но е много по-добре с компетентен съвет :)
В началото, като четох сорсовете на Инди нишките, реших, че може да се работи с тяхното събитие OnStop (или OnStoping ли беше?) и си мислех, че това е механизъм да спра подходящо нишката, да си свърша работата и да продължа нишката.
Може и да има такава хватка, ама не я разбрах как става.
Разликата, с това, което предлагаш не е голяма и дори, ако има такъв механизъм в Инди, той ми се струва излишен (сложили са го за "стил").
Благодаря ти още веднъж!
Re: OK
andrew_nikoloff e прав. Не трябва да излизаш от събитието. В това събитие ти си в контекста на тази нишка. Не си в main thread-a на приложението. Правиш си заявката към другото приложение, чакаш я и като дойде отговора си готов и излизаш от събитието. Това е правилният начин.
Остава да тествам
Остава да тествам.
Пробата я пуснах, даже работи.
Сложих един tThreadList за синхронизиране между нишките на заявките и интерфейса с другото приложение.
Значи, както предложихте, нишката си спи (sleep) и на 500мс проверява дали в tThreadList се среща указателят й. Ако се среща - взема си данните и унищожава елемента от списъка (обектите в tThreadList имат указател на нишката и данни или инфо за таймаут).
Инди-то все още ми е доста мъгляво и ми е мнго ценна помощта от форума.
---
В момента се опитвам да тормозя програмките с повече заявки.
Пробата я пуснах, даже работи.
Сложих един tThreadList за синхронизиране между нишките на заявките и интерфейса с другото приложение.
Значи, както предложихте, нишката си спи (sleep) и на 500мс проверява дали в tThreadList се среща указателят й. Ако се среща - взема си данните и унищожава елемента от списъка (обектите в tThreadList имат указател на нишката и данни или инфо за таймаут).
Инди-то все още ми е доста мъгляво и ми е мнго ценна помощта от форума.
---
В момента се опитвам да тормозя програмките с повече заявки.
Редактирано от NikB на
Грешки, грешки. Дали има свестни сорсове на Indy?
Грешки, грешки. Дали има свестни сорсове на Indy?
Ползвам инсталацията [линк]
Когато я ползвам директно, така, както се инсталира сама, има несъответствие между сорсовете и кога (при дебъг) - първата картинка (dcu файловете се вземат от папка LibD7, a сорсът е в source:
Като деинсталирам, компилирам и инсталирам това, което е в source дава другата грешка (53-та или 54-та):
Да, май има още да се мотам с това Indy.
Ползвам инсталацията [линк]
Когато я ползвам директно, така, както се инсталира сама, има несъответствие между сорсовете и кога (при дебъг) - първата картинка (dcu файловете се вземат от папка LibD7, a сорсът е в source:
Като деинсталирам, компилирам и инсталирам това, което е в source дава другата грешка (53-та или 54-та):
Да, май има още да се мотам с това Indy.
Да, освен сорсовете, грешката е на експеримента
Основния проблем се оказа на експеримента - страницата, която тестово тегли данни много често изпраща заявки.
Мисля, че в тоя случей е нормално да излиза 10053 или 10054-та грешка (дисконектване или аборт на конекта), защото една и съща страница прави заявка преди да е завършена предходната й заявка.
Вероятно става нещо такова.
Ако някой има друго обяснение - ще е полезно :)
Мисля, че в тоя случей е нормално да излиза 10053 или 10054-та грешка (дисконектване или аборт на конекта), защото една и съща страница прави заявка преди да е завършена предходната й заявка.
Вероятно става нещо такова.
Ако някой има друго обяснение - ще е полезно :)
Re: Да, освен сорсовете, грешката е на експеримента
Ползвай Indy 9.0.50. Много по-читава е и съдържа много bug fixes.
[линк]
[линк]
Re: Впечетлен съм
За подобно нещо аз бих използвал един от следните два начина:
1. Подобно на твоята първа идея, първия тред крейтва и стартира втория, после се съспендва. Когато втория си свърши работата резумва първия.
2. Първия крейтва и стартира втория и чака неговото терминиране с WaitForSingleObject. В този случай втория тред трябва да се терминира сам като свърши работата. Този е по- добрия вариант, защото WaitForSingleObject има таймаут така че ако втория тред нещо заспи или се забави, ще може първия тред да продължи и да даде отговор за грешка или нещо подобно. Това е близко до варианта със Sleep, ама аз Sleep не го харесвам.
1. Подобно на твоята първа идея, първия тред крейтва и стартира втория, после се съспендва. Когато втория си свърши работата резумва първия.
2. Първия крейтва и стартира втория и чака неговото терминиране с WaitForSingleObject. В този случай втория тред трябва да се терминира сам като свърши работата. Този е по- добрия вариант, защото WaitForSingleObject има таймаут така че ако втория тред нещо заспи или се забави, ще може първия тред да продължи и да даде отговор за грешка или нещо подобно. Това е близко до варианта със Sleep, ама аз Sleep не го харесвам.
Редактирано от vido на
Мога да пробвам :)
Мога да пробвам :)
Направи ми впечетление, че на Инди нишките са добавени още методи и свойства за контррол на спирането и пускането на нишките, а не намирам описание как се ползват - това ми е притеснението :).
В приложението ми данните (които очква Инди нишката) се получават през TCP през нормални (не Инди) сокет в неблокиращ режим и нямам проблеми с многонишковостта (самите сокето я осигуряват).
От нишката на Инди към главната нишка комуникирам със съобщения . Главнаат нишка стартира обмена по другите сокети.
В събитията на другите сокети (когато се получат данните) работя с един инди нишков списък, през който предавам данните на Инди нишката.
ТУК МОГА ДА ПРОБВАМ ТВОЯТА ИДЕЯ - вместо в нишката да слягам sleep(400), да я спирам, да предавам указателят й към другите сокети, и като се получат данните да стартирам отново Indi нишката.
Направи ми впечетление, че на Инди нишките са добавени още методи и свойства за контррол на спирането и пускането на нишките, а не намирам описание как се ползват - това ми е притеснението :).
В приложението ми данните (които очква Инди нишката) се получават през TCP през нормални (не Инди) сокет в неблокиращ режим и нямам проблеми с многонишковостта (самите сокето я осигуряват).
От нишката на Инди към главната нишка комуникирам със съобщения . Главнаат нишка стартира обмена по другите сокети.
В събитията на другите сокети (когато се получат данните) работя с един инди нишков списък, през който предавам данните на Инди нишката.
ТУК МОГА ДА ПРОБВАМ ТВОЯТА ИДЕЯ - вместо в нишката да слягам sleep(400), да я спирам, да предавам указателят й към другите сокети, и като се получат данните да стартирам отново Indi нишката.
Re: Мога да пробвам :)
Моето скромно мнение - никога Sleep! Поне за мен, Sleep процедура е от ерата на Делфи 1, когато се работеше под Виндовс 3.11. Използвай WaitFor.. и други механизми за синхронизация. Иначе - проблеми...
Re: Мога да пробвам :)
Само внимавай другите (нормалните) сокети да не се забавят или да заспят, че няма кой да събуди първата (инди) нишка. Затова варианта с WaitForSingleObject е за предпочитане. Освен това можеш да го замениш с WaitForMultiObject и/или да синхронизираш с ивънти (вместо съобщения) По този начин можеш да "пускаш" инди нишката от много места, дори тя ще знае (WaitForMultiObject връща от какво е активирана) точно от кой е събудена докато е чакала на WaitForMultiObject. А за допълнителните неща за инди нишките не мода да дам съвет. Това съм го използвал само с простите тредове.
В действителност
В действителност, за Win 3 sleep е убийство, защото там многонишковостта в абсолютно дърво.
В Win32 нагоре няма никакъв проблем и sleep на някоя нишка не пречи на ефективността на останалите.
В Win32 нагоре няма никакъв проблем и sleep на някоя нишка не пречи на ефективността на останалите.
Blagodaria :)
Blagodaria :)
Там интерфейсът е отработен с години - има таймаути - няма страшно.
Не разбрах за ивънтите - в посока от стандартните сокети - да първопричината са ивънти - това ли имаш предвид.
Там интерфейсът е отработен с години - има таймаути - няма страшно.
Не разбрах за ивънтите - в посока от стандартните сокети - да първопричината са ивънти - това ли имаш предвид.
Re: Blagodaria :)
Имах предвид че с WaitForMultiObject първия тред може да чака освен терминирането на втория тред и разни други Event-и за синхронизация или логване например. Първия параметър на WaitForMultiObject е масив от хендъли, които може да са както хендъли на тредове така и хендъли на ивънти (и разни други също). Преди време правих сървис, който на всяка заявка пуска една двойка тредове, единия циклещ на WaitForMultiObject през половин секунда и чакащ втория, който върши истинската работа (в моя случай заявки към база). Когато обаче искаш да спреш сървиса, основния тред (различен от тези двойки) сетва ивънт който се прихваща от първия тред от двойката и той терминира (ако трябва и грубо) втория. Идеята е основния тред само да дава задачи и команди. Предполагам че в твоя случай повечето от тези неща са на готово от инди сокетите или TCP сървара. В моя заявките идваха през шер памет и други ивънти. Я колко много писах :)
Re: Blagodaria :)
За това с комбинацията от нишки не бях се сещал.
Благодаря ти за подробното описание на идеята.
В действителност, проекта доста прилича на твоя.
Един апликайшън сървър, събира данни от измерватели, поддържа актуалното им състояние в свои обекти и пише хронология в БД сървър.
Един WEB сървър получава разни заявки (за актуално състояние или за хронологии или за обобщени справки), препраща ги към апликейшън сървъра и т.н.
Общо взето с Indy 9.0.19 имаше някои проблеми, от ден-два всичко май е ОК - остава рутинната хамалогия.
До скоро (за друг проект) се налагаше да синхринизирам (в известен смисъл) няколко БД сървъра и го правех с няколко нишки, но не съм се сещал една "бърза" нишка да се грижи за по-бавна.
Благодаря ти за подробното описание на идеята.
В действителност, проекта доста прилича на твоя.
Един апликайшън сървър, събира данни от измерватели, поддържа актуалното им състояние в свои обекти и пише хронология в БД сървър.
Един WEB сървър получава разни заявки (за актуално състояние или за хронологии или за обобщени справки), препраща ги към апликейшън сървъра и т.н.
Общо взето с Indy 9.0.19 имаше някои проблеми, от ден-два всичко май е ОК - остава рутинната хамалогия.
До скоро (за друг проект) се налагаше да синхринизирам (в известен смисъл) няколко БД сървъра и го правех с няколко нишки, но не съм се сещал една "бърза" нишка да се грижи за по-бавна.