Остановка потоков в Delphi Indy без ожидания окончания тайм-аута - PullRequest
3 голосов
/ 02 марта 2012

Это первый раз, когда я работаю над многопоточным приложением с Delphi, так что для меня все еще хорошо, но я много читаю.

Моя тема проста, если быть кратким, я просто использую Indy (IdHTTP) для получения содержимого веб-страницы, а затем проверяю, содержит ли содержимое строку. Здесь нет проблем.

Теперь для завершения потоков я использую логическое значение с WHILE DO. Кажется, работает, но вот проблема: как я использую Timeout с Indy, иногда я должен ждать окончания периода ожидания до окончания потоков (когда сервер, например, не отвечает) ...

Это раздражает, особенно когда я использую +200 потоков. В других программах, использующих многопоточность и аналогичные процедуры, когда я нажимаю «Стоп», все останавливается через несколько секунд, и это то, что мне нужно.

Я прочитал, что должен использовать AntiFreeze, чтобы IdHTTP мог "читать мои инструкции" ...

Итак, я немного растерялся здесь. Я не думаю, что это очень необходимо, но вот мой код: http://pastebin.com/G7De8bgb

Заранее спасибо за фары:)

Beny

Ответы [ 2 ]

6 голосов
/ 02 марта 2012

Класс TidHTTP имеет событие OnWork.Используйте это событие, чтобы отменить загрузку или выгрузку данных.Как отменить это событие?Вызвать исключение молчания Abort.

Это псевдокод:

THTTPThread = class(TThread)
    private
        HTTPComponent: TidHTTP;
        procedure OnHTTPProgress(ASender: TObject; AWorkMode: TWorkMode;
                                     AWorkCount: Int64);
    published
        procedure execute();
end;

implementation
procedure THTTPThread.execute;
begin
    Self.HTTPComponent := TidHTTP.Create(nil);
    with HTTPComponent do
    begin
        OnWork := Self.OnHTTPProgress;
        Get('http://www.google.com');
    end;
end;

procedure THTTPThread.OnHTTPProgress(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin

    if Self.Terminated then
        Abort;
end;

Учтите, что этапы, на которых вызывается OnWork, являются случайными.Событие может быть вызвано в середине запроса, в начале или даже в конце.Приведенный выше код будет работать так, как если бы вы нажимали кнопку остановки в браузере.

[ОБНОВЛЕНИЕ] Забудьте о том, что если затем событие OnWork не вызывается, когда поток висит для ответа сервера,Команда use может использовать тайм-аут, если «последний ответ» был получен заданные миллисекунды назад.Для этого используйте GetTickCount.

2 голосов
/ 02 марта 2012

У меня была похожая проблема с использованием Indy и веб-сервисов, когда система, о которой мы говорили, тоже была в лучшем случае ненадежной (мне пришлось установить тайм-аут чтения на 30 минут для некоторых вызовов).

После звонков в Рио(и ваши IdHTTP) вызовы блокируют, вы не можете отменить или прервать их напрямую.

Однако вы можете (при использовании других потоков) отключить базовый сокет, что вызовет исключение в get / webcall.

Я сделал быстрый взлом, чтобы проверить идею, используя только TIdHTTP, и она, кажется, работает так же, как и с Rio.

В вашем основном / управляющем потоке вам нужно вызвать IDHTTP.Disconnect, затемпоймать исключение, которое будет возбуждено в вашей ветке.Взглянув на свой код, вы создаете IdHTTP в Thread.Execute, вы должны будете перенести его объявление в конструктор класса, чтобы позволить функции Abort в вашем классе потока просто отключить сокет.

Я использовал Delph 7 и INDY10, только если это отличается от вашей настройки.

Надеюсь, это поможет

BTW

Если кто-нибудь знает о лучшем/ менее агрессивный метод, я бы тоже хотел это увидеть.

...