-
Добрый день!
Наверняка многие сталкивались с проблемой легкого "подвисания" машины при передаче электронки через TIdSMTP. Наверное есть куча материала в инете, но находясь в командировке катастрофически не хватает времени поизучать материал. В связи с этим прошу прокоментировать что в нижеследующем коде нужно изменить для устранения замерзания приложения.
function SendEmail(FileName, Theme, Letter, Sender, Email: String): String; var IdSMTP: TIdSMTP; IdMessage: TIdMessage; Attach: TidAttachment; Msg: tidmessage; begin Result := '' //if not IsInternetConnected() then Exit; IdSMTP := TIdSMTP.Create(nil); IdMessage := TIdMessage.Create(nil); try IdSMTP.AuthenticationType:= atLogin; IdSMTP.Username := 'robot'; IdSMTP.Password := '12345'; IdSMTP.Host := 'smtp.mail.ru'; IdSMTP.Port := 25; Msg := TIdMessage.Create(nil); Msg.Body.Add(Letter); Msg.Subject := Theme; Msg.From.Address := 'robot@mail.ru'; Msg.From.Name := Sender; Msg.Recipients.EMailAddresses := Email; Msg.IsEncoded := true; if FileName <> '' then Attach := TIdAttachment.Create(msg.MessageParts, FileName); Application.ProcessMessages; try try IdSMTP.Connect; //(1000); IdSMTP.Send(msg); Application.ProcessMessages; except on E: Exception do Result := 'ERROR occured during email send: ' + E.Message; end; finally if IdSMTP.Connected then IdSMTP.Disconnect; end; Application.ProcessMessages; finally IdSMTP.Free; FreeAndNil(Attach); IdMessage.Free; end; end;
-
> [0] Alik (24.09.11 19:20)
где именно "замерзает"?
-
> Eraser © (24.09.11 22:50) [1] > > [0] Alik (24.09.11 19:20) > > где именно "замерзает"?
Все приложение виснет, пока IdSMTP не завершит свои дела. Если интернет быстрый, то этого можно и не заметить.
Может кинуть на форму IdAntefreeze ?
-
В отдельный поток запихни... :) Форма не будет замирать. IdAntefreeze это Application.ProcessMessages только по таймеру срабатывает...
-
> Все приложение виснет, пока IdSMTP не завершит свои дела. >
Ну так ИНДИ это синхронные методы работы
-
> FireMan_Alexey © (25.09.11 10:23) [3] > В отдельный поток запихни... :) > Форма не будет замирать. > IdAntefreeze это Application.ProcessMessages только по таймеру > срабатывает...
А куда поставить, в Synchronize ?
-
> Anatoly Podgoretsky © (25.09.11 14:36) [4] > > > Все приложение виснет, пока IdSMTP не завершит свои дела. > > > > > Ну так ИНДИ это синхронные методы работы
Да, я бегло просмотрел Ваш перевод "Глубины инди", инди это в основном блокированный режим.
Но предложение FireMan_Alexey по отправке в поточном методе должно сработать?
-
> [5] Alik (25.09.11 19:10)
> А куда поставить, в Synchronize ?
лучше никуда. отправил письмо, поток уничтожился и вызвал OnTerminate в основном потоке. это предпочтительный и самый простой сценарий.
-
Я имел ввиду, что твой код отправки сообщения запихнуть в отдельный поток. За Synchronize вообще забудь, он нужен только для синхронного вывода на форму!!! Тебе стоит лишь контролировать с каким кодом завершился поток, и если произошла ошибка передачи, то реагировать соответствующим образом...
Частое использование Application.ProcessMessages, говорит о неправильном алгоритме, т.к. данная процедура как минимум замедляет выполнение программы с вытекающими последствиями...
-
> Alik (25.09.2011 19:12:06) [6]
Все блокирующие методы должны использоваться в потоках, если нет времени ждать.
-
> Eraser (25.09.2011 23:32:07) [7]
вызвал OnTerminate, поток уничтожился
-
> FireMan_Alexey (26.09.2011 01:20:08) [8]
ProcessMessages минимум замедляет выполнение программы всего лишь на несколько наносекунд.
-
> Anatoly Podgoretsky ©
Я проверял при просчете алгоритмов пересечения плоскостей с вектором, при отсутствии в цикле ProcessMessages ~170000 тыс плоскостей в секунду, с ProcessMessages ~120000 тыс. плоск/сек.
-
> FireMan_Alexey (27.09.2011 01:31:12) [12]
У тебя наверно много чего в ProcessMessages, например перерисовка интерфейса.
-
> Я проверял как проверял? код. ProcessMessages сам ничего не занимает, но он дает возможность обработки событий (даже по названию) и если ты их там в цикле инициализируешь (ну вот "просчет" у тебя наверняка не просто считает а еще и рисует?)... то считаешь ты время их исполнения, а не время ProcessMessages. а без него в цикле событие выполнилось 1 раз, сколько бы ты там в цикле изменений не сделал.
-
> sniknik © T:=GetTickCount;
I:=0;
While T+1000>GetTickCount do
Begin
...
Inc(I);
End; Прорисовки просчетов не было. Одна кнопка. Кол-во выводилось ShowMessage- ом. Когда тестил, хотел узнать сколько мой 1,4ГГц проц сможет посчитать плоскостей в пространстве... Вычисления были с синусами/косинусами, возможно это повлияло, спорить не буду, но как мне показалось, все таки изменения в скорости данная процедура дает(ИМХО)
-
Тут немаловажное значение имеет частота вызова ProcessMessages. Если идет обработка миллиона элементов, то вызов после обработки каждого элемента неблагоразумен. Вполне разумно при обработке больших данных вызывать этот метод раз в полсекунды. GetTickcount в помощь.
-
> [15] FireMan_Alexey © (27.09.11 12:11)
> Прорисовки просчетов не было. Одна кнопка. Кол-во выводилось > ShowMessage- ом.
это не очень хорошая практика. лучше, в данном случае, всю операцию производить в потоке, а состояние выполнение обновлять в GUI по таймеру, например, раз в секунду. так же не забывать про защиту критической секцией.
-
> все таки изменения в скорости данная процедура дает(ИМХО) но считаешь то ты не скорость... количество циклов за промежуток времени. вот скорость procedure TForm1.Button3Click(Sender: TObject);
var
T: DWORD;
i: integer;
begin
T:= GetTickCount;
for i:= 1 to 100000 do
Application.ProcessMessages;
Edit1.Text:= IntToStr(GetTickCount - T);
end;
procedure TForm1.Button4Click(Sender: TObject);
var
T: DWORD;
i: integer;
begin
T:= GetTickCount;
for i:= 1 to 100000 do;
Edit2.Text:= IntToStr(GetTickCount - T);
end; 0 сек на 100000 в обоих случаях, а вот 1000000 уже (на моем компе) 31 тик в первом случае и тот же 0 во втором т.е. 31/1000 секунды на 1000000 итераций т.е. 0,031/1000000 секунды для 1го "чистого" Application.ProcessMessages;. > Если идет обработка миллиона элементов ну вон для миллиона = 0,031 сек. критично? в отличие от если идет перерисовка, то этом миллион может на час растянутся к примеру.
-
>sniknik © Я же говорил, что считаю кол-во пересечений с плоскостями :), смотри [12] ;) Я не возражаю, что возможно на твоем проце ProcessMessages выполняется за такой промежуток времени/тиков, я лишь проводил эксперимент для себя и сделал для СЕБЯ вывод, что задержка все-таки существует, а если добавить еще и прорисовку, то время задержки увеличиться... :) Админ - прости, что отклонились от темы топик стартера!
|