#multithreading #delphi #delphi-xe #indy #idhttp
#многопоточность #delphi #delphi-xe #indy #idhttp
Вопрос:
Я новичок в Multithreading
, у меня есть процедура, которая выполняет серию операций с использованием indy (вход на сайт и загрузка файлов и …), иногда, когда сайт не реагирует или это занимает слишком много времени, исключения не возникает даже при заданном значении idHttp.connectTimeout
и idHttp.readTimeout
, или иногда это происходит, но не в указанное мной время !!, вот почему я предпочитаю проверить задачу и посмотреть, выполняется ли, например, ITask
в течение 30 сек, это должно быть прекращено!, я пытался использовать itask.cancel
, но это отменяет только в том случае, если что-то находится в очереди и не завершает задачу, которая уже запущена, каково решение моей проблемы?
просто чтобы вы знали, что происходит в моей программе :
изначально моя программа создает классы на основе списка профилей и запускает процесс входа в систему и загрузки, я хочу завершить любой startDownloadProcess
, который занимает более 30 секунд
вот пример кода :
// this is what i used to do
for I := 0 to mProfileList.count - 1 do
begin
myClass := TMyClass.create(mProfileList[i]);
//sometimes this takes a very very long time and i don't want that.
myClass.startDownloadProcess;
end;
// here is what i have in mind
for I := 0 to mProfileList.count - 1 do
begin
mITaskArray[i] := TTask.run(procedure
begin
myClass := TMyClass.create(mProfileList[i]);
myClass.startDownloadProcess;
end);
end;
Что мне нужно :
я хочу, чтобы каждая задача зависела от предыдущей (очереди) и ждала, пока предыдущая не завершится, и если задача занимает более 30 секунд, она завершается, и очередь продолжается.
теперь я знаю, что в этом коде может быть много чего неправильного, но именно поэтому я здесь, я немного не понимаю, как действовать дальше и правильно ли то, что я делаю вообще!
Комментарии:
1. Вы должны регулярно проверять внутри задачи, отменяется ли она:
if TTask.CurrentTask.Status = TTaskStatus.Canceled then exit;
2. @LURD но разве задача не выполняется только один раз?, если да, то как я могу проверить статус, если он застрял в строке (например, IdHTTP.get());
3. Вы не можете завершать задачи и потоки извне. Вам нужно, чтобы они сотрудничали. Вы можете завершать процессы.
4. Именно то, что уже было предложено
5. @LURD
TTask
, неTIdHTTP
выполняется в своем собственном потоке.TIdHTTP
выполняет свою работу в любом вызываемом потокеGet
/Post
. Но это не имеет значения, посколькуOnWork
события запускаются только при активном обмене байтами, поэтому, если сайт не отвечает, тогда нет активности сокета для запуска событий. Вы должны использовать тайм-ауты сокета. Обязательно используйтеConnectTimeout
иReadTimeout
(в Indy их нетSendTimeout
, но у базового сокета есть свояSO_SNDTIMEO
опция на уровне API), а также рассмотрите возможность включения TCP keepalives.
Ответ №1:
вы говорите, что вы новичок в многопоточности, поэтому помните, что никогда (never) не используйте TTASK / ITask или аналогичный TParalel. это полностью глючит! используйте вместо TAnonymousThread
MyThread := TThread.createAnonymousThread(
Procedure
Begin
repeat
if MyThread.checkterminated then exit;
if moreThan30secondsRunning then exit;
....
until wordDone;
end).start;