-
При переходе на Indy10 стал виснуть сервер при попытке его остановки, если есть подключенные клиенты. Останавливается как обычно: IdHTTPServer.Active := false;
Сервер отправляет данные клиентам. Данные бесконечны, поэтому обработчик IdHTTPServerCommandGet выглядит примерно так:
procedure TfrmMain.IdHTTPServerCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
....
while AContext.Connection.Connected do
begin
.... тут отсылаем данные ....
sleep(0);
....
end;
...
end;
В предыдущей версии Indy все работало. В новой висит на цикле. Если цикл убрать, то не виснет. Виснет даже с пустым циклом.
Как с этим бороться?
-
Что-то типа
трай
сессионнс.локлист
фор нуль до конца ду гасить колиентов
файнали
анлоклист
енд
-
> DVM (09.06.2008 14:19:00) [0]
В коде не видать IdHTTPServer.Active := false;
-
> Anatoly Podgoretsky © (09.06.08 14:43) [2]
procedure TfrmMain.btnStopClick(Sender: TObject);
var
Lst: TList;
begin
IdHTTPServer.StopListening;
Lst := IdHTTPServer.Contexts.LockList;
try
while Lst.Count > 0 do
TIdContext(Lst.Items[0]).Connection.Disconnect;
finally
IdHTTPServer.Contexts.UnlockList;
end;
IdHTTPServer.Active := false;
end;
Виснет все равно.
-
Теперь не видать удаление элементов из Lst или этим Инди занимается.
Второе, а ты точно дождался окончания операции Disconnect для каждого элемента списка, это может занимать очень много времени.
Почему бы для отладки не выводить в метку значение Lst.Count? Тогда сраду будет видно.
Третье, а в позицию IdHTTPServer.Contexts.UnlockList или IdHTTPServer.Active := false; управление попадает, это же ты должен провести отладку, а не мы.
Ответь на какой строке у тебя зависает?
-
> Теперь не видать удаление элементов из Lst или этим Инди
> занимается.
Этим должна заниматься инди вообще то. Я немного неправильно написал вверху, наверное, лучше так, наверное, но это дела не меняет:
for i := 0 to Lst.Count - 1 do
TIdContext(Lst.Items[i]).Connection.Disconnect;
> Ответь на какой строке у тебя зависает?
IdHTTPServer.Active := false;
> Второе, а ты точно дождался окончания операции Disconnect
> для каждого элемента списка, это может занимать очень много
> времени.
Нет, не дожидаюсь. Но дело в том, что IdHTTPServer.Active := false; сам по идее должен ждать окончания всех соединений, он и ждет. И не дожидается.
-
> DVM (09.06.2008 15:24:05) [5]
Неправильно ты написал сейчас, готовься к исключению.
>> Ответь на какой строке у тебя зависает?
> IdHTTPServer.Active := false;
Означает ли, что ты сюда получаешь управление?
-
> Неправильно ты написал сейчас, готовься к исключению.
Лист залочен и не изменится, какие исключения? Я лишь оповещаю потоки, что пора закругляться. Воообще все эти строки TIdContext(Lst.Items[i]).Connection.Disconnect;
лишние. В предыдущей версии Инди все работало и само прекрасно завершалось одной строкой IdHTTPServer.Active := false;
> Означает ли, что ты сюда получаешь управление?
>
Да. И дальше пошло поехало в дебри инди, в которых я погряз, пытаясь разобраться где там зависает.
-
Я лишь оповещаю потоки, что пора закругляться.
А им с их синхронными методами по барабану оповещения если конечно нет таймаутов
-
> А им с их синхронными методами по барабану оповещения если
> конечно нет таймаутов
Ну дык в каждом потоке, крутится мой цикл (см выше), который проверяет флаг Connected.
Я так понял вначале, что выполнение метода TIdContext(Lst.Items[i]).Connection.Disconnect; аналогично TThread.Terminate в VCL и устанавливает флаг закругления. Оказывается все не так.
-
Вобщем, нашел я ошибку свою и решение.
В цикле было в коде подавление всех исключений без разбору:
while AContext.Connection.Connected do
begin
....
try
AResponseInfo.WriteContent;
except
end;
...
end;
что делало невозможным установку флага Connected со стороны потока, т.к. формально ошибок никаких не возникало (просто неоткуда). Странно, что это работало в предыдущей версии Инди. Если сделать выход по исключению, то все нормально работает.
while AContext.Connection.Connected do
begin
....
try
AResponseInfo.WriteContent;
except
exit;
end;
...
end;
-
В догонку, может кому пригодится.
Еще более правильно и надежно подправить так:
while ((not (AContext.Yarn as TIdYarnOfThread).Thread.Terminated) and (AContext.Connection.Connected)) do
begin
...
end;