Нуждаюсь в "асинхронном" запуске процедур (НЕ ПОТОКИ, скорее события который запускают код параллельно). В основном потоке (форме) это всё решается через мини-библиотеку OneShotTimer, в которой есть SetTimeout, и выходит что для асинхронного запуска надо всего-лишь => SetTimeout(proc,0); и он запускает процедуру параллельно Но в потоках такое не покатывает, ибо эта функция сделана на SetTimer, который посылает сообщения, а потоки-то с ними не умеют работать... Нужен какой-то аналог, как можно в потоке запустить процедуру параллельно. Кто что посоветует? п.с. кто еще не понял - параллельно это как в событии, вот у вас есть процедура, которая выполняется в цикле, всё гуд работает, и если, когда она работает, в VCL нажать какую-либо кнопку на которой onClick, то он запустится параллельно той - что выполняется в данный момент. Именно такой эфект мне и нужен. п.п.с. вот сама либа OneShotTimer, если кому интересно: Code: unit OneShotTimer; interface uses Windows, Generics.Collections; type TOnTimerProc = reference to procedure; procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal); var TimerList: TDictionary<UINT_PTR, TOnTimerProc>; implementation procedure TimerProc(hwnd: HWND; uMsg: UINT; idEvent: UINT_PTR; dwTime: DWORD); stdcall; var Proc: TOnTimerProc; begin if TimerList.TryGetValue(idEvent, Proc) then try KillTimer(0, idEvent); Proc(); finally TimerList.Remove(idEvent); end; end; procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal); begin TimerList.Add(SetTimer(0, 0, ATimeout, @TimerProc), AProc); end; initialization TimerList := TDictionary<UINT_PTR, TOnTimerProc>.Create; finalization TimerList.Free; end. // http://stackoverflow.com/a/10469878
При событиях код запускается не параллельно, а последовательно, то есть синхронно. Если в OnClick кнопки написать sleep(5000); то вся форма зависнет на 5 сек. Посмотри на эти библиотеки, может быть что подойдет: AsyncCalls, OmniThreadLibrary
Они оба "играются" с потоками (отдельными) и синхронизациями, а меня это не устраивает, мне надо запустить выполнение кода в ЭТОМ-ЖЕ потоке на вторым действием, параллельным, БЕЗ СОЗДАНИЯ ОТДЕЛЬНОГО ПОТОКА, в этом и весь-то гемор!
Вообще то там потоки создаются только один раз и добавляются в пул. Если хочешь, чтобы SetTimer работал в каком то другом потоке (не в главном), сделай в этом потоке Message Loop.
Последние 4 часа с этим и тружусь. Мессаж луп - весь поток повесит если в цикле, надо как-то из основного потока передавать мессаги в поток, я щас тружусь-тружусь но пока ничего Code: procedure WM_TIMER(var Msg: TMessage); message WM_TIMER; // эта процедура в основном потоке событие просто тупо не срабатывает
Уточни еще кое что. Тебе нужно запустить код с помощью события в дополнительном потоке. Какой поток должен инициировать вызов? Главный или тот самый дополнительный, который позже вызовет твою функцию? Судя по всему второй вариант. Тогда твой алгоритм может выглядеть примерно так: 0. Выполняешь в потоке любой код и в нем с помощью этой же библиотеки OneShotTimer делаешь вызовы функции SetTimeout с теми параметрами, которые тебе требуются и в нужном тебе количестве. 1. Запускаешь Message Loop. Все, этого должно быть достаточно, чтобы твои функции, которые ты вызвал с помощью SetTimeout, выполнились. Зачем? Если из основного потока нужно делать асинхронные вызовы, лучше используй одну из двух библиотек, которые написал выше. Также можешь посмотреть код метода TThread.Synchronize, он запускает код из дополнительного потока в основном, но работает как раз с помощью посылки сообщения основному потоку.
Вариант 2. Нет, Ты не понял! Поток никак не должен быть связан с главным (в идеале) в самом потоке, работающем в реальном времени - нужно вызвать без задержки самого потока процедуру т.е. procedure execute; begin ............. ............. ............. .....код..... ............. ............. ............. ChechServerOnBalance; // запрос сам выполняется допустим 30 секунд к серваку, т.е. подвиснет на 30 сек интерфейс, а мне нужно чтоб он запустился ПАРАЛЕЛЬНО и не в потоке, так-же как и запускает таймер всё. ............. ..работаем далее, без зависаний, пока проверяется баланс.. ............. end; пример с "проверкой баланса" дан как пример понять смысл, аналогично ему будет sleep(30000);, т.е. по сути - там не запрос, а другая процедура с другими назначениями. еще как пример, дабы больше сделать понимание проблемы (уже ближе к сути) раньше был асинхронный запрос по инету, т.е. d:=Create(True); d.Send(...) d.Resume; и далее работает код........... а потом, когда приходит ответ - этот запрос вызывает callback в потоке, и он выполяется вот мне надо сделать аналог этой-же ситуации, но без создания потока, т.е. запрос отправился - он интерфейс ОТПУСТИЛ, код дальше выполнился. а ответ пришёл - он дёрнул каллбеком его ибо сейчас получается что идёт: запрос => выполняется, и вызывает каллбек1, каллбек1 шлёт запрос2 => вызывается каллбек2, который шлёт запрос 3 =>............ и получается, что связь полностью синхронная, и засчёт этого если есть код, ПОСЛЕ посылки запроса - то он выполнен не будет пока вся цепочка запросов-каллбеков не дойдёт до конца а мне надо его послать => выполнить код под ним => ожидать пока он дёрнет каллбек п.с. и даже как я понимаю - то он даже не параллельно выполняется (вот только допёр) а просто останавливает выполнение основного потока и выполняет себя потом, но поскольку даже 100ms хватает чтоб выполнить все "нижние" процессы то кажется будто он выполняется параллельно основному коду. Но всё-же это лучше, когда он "отпускает интерфейс" и даёт выполнятся коду далее, этого и надо достичь.
Mixon, все ясно. То что ты описал - это асинхронный ввод/вывод. В Delphi для этого есть хорошая библиотека Overbyte ICS. Она как раз позволяет выполнить асинхронный запрос, например, на скачивание какой нибудь страницы по протоколу HTTP и обработать ответ с помощью коллбека после того, как он придет. При этом после отправки запроса программа продолжит свое выполнение, а не как в случае, например, с теми же Indy или Synapse зависнет. Message Loop нужен обязательно.
Ну тк а как мне этот мессаже-луп так всунуть чтоб он-то поток не подвешивал??? п.с. зайди в аську плиз, так проще будет!)))
0. Выполняешь любой код, запускаешь асинхронные запросы. В коллбеках на эти запросы должен быть, нужный тебе код а также запуск новых запросов, если надо (то есть цепочка запросов получается). 1. Message Loop. В любом случае цикл сообщений "подвешит" твой поток, но благодаря колбекам на запросы он будет "оживать", обрабатывать запросы и запускать новые.
как я понял - ICS - это тупо другая либа аналог сунапса но без позвешивания. а мне нужно конкретно с сунапсом сделать так
С Synapse получится сделать только через пул потоков и никак иначе, ибо Synapse сделан для синхронной работы с сетью, тогда как ICS - для асинхронной.