Конференция "Сети" » Подвисание приложения при передаче письма через TIdSMTP [D7, WinXP]
 
  • Alik (24.09.11 19:20) [0]
    Добрый день!

    Наверняка многие сталкивались с проблемой легкого "подвисания" машины при передаче электронки через 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;
  • Eraser © (24.09.11 22:50) [1]
    > [0] Alik   (24.09.11 19:20)

    где именно "замерзает"?
  • Alik (25.09.11 08:39) [2]

    > Eraser ©   (24.09.11 22:50) [1]
    > > [0] Alik   (24.09.11 19:20)
    >
    > где именно "замерзает"?


    Все приложение виснет, пока IdSMTP не завершит свои дела. Если интернет быстрый, то этого можно и не заметить.

    Может кинуть на форму IdAntefreeze ?
  • FireMan_Alexey © (25.09.11 10:23) [3]
    В отдельный поток запихни... :)
    Форма не будет замирать.
    IdAntefreeze это Application.ProcessMessages только по таймеру срабатывает...
  • Anatoly Podgoretsky © (25.09.11 14:36) [4]

    > Все приложение виснет, пока IdSMTP не завершит свои дела.
    >  

    Ну так ИНДИ это синхронные методы работы
  • Alik (25.09.11 19:10) [5]

    > FireMan_Alexey ©   (25.09.11 10:23) [3]
    > В отдельный поток запихни... :)
    > Форма не будет замирать.
    > IdAntefreeze это Application.ProcessMessages только по таймеру
    > срабатывает...


    А куда поставить, в Synchronize ?
  • Alik (25.09.11 19:12) [6]

    > Anatoly Podgoretsky ©   (25.09.11 14:36) [4]
    >
    > > Все приложение виснет, пока IdSMTP не завершит свои дела.
    >
    > >  
    >
    > Ну так ИНДИ это синхронные методы работы


    Да, я бегло просмотрел Ваш перевод "Глубины инди", инди это в основном блокированный режим.

    Но предложение FireMan_Alexey по отправке в поточном методе должно сработать?
  • Eraser © (25.09.11 23:32) [7]
    > [5] Alik   (25.09.11 19:10)


    > А куда поставить, в Synchronize ?

    лучше никуда. отправил письмо, поток уничтожился и вызвал OnTerminate в основном потоке. это предпочтительный и самый простой сценарий.
  • FireMan_Alexey © (26.09.11 01:20) [8]
    Я имел ввиду, что твой код отправки сообщения запихнуть в отдельный поток.
    За Synchronize вообще забудь, он нужен только для синхронного вывода на форму!!!
    Тебе стоит лишь контролировать с каким кодом завершился поток, и если произошла ошибка передачи, то реагировать соответствующим образом...

    Частое использование Application.ProcessMessages, говорит о неправильном алгоритме, т.к. данная процедура как минимум замедляет выполнение программы с вытекающими последствиями...
  • Anatoly Podgoretsky © (26.09.11 17:49) [9]
    > Alik  (25.09.2011 19:12:06)  [6]

    Все блокирующие методы должны использоваться в потоках, если нет времени
    ждать.
  • Anatoly Podgoretsky © (26.09.11 21:09) [10]
    > Eraser  (25.09.2011 23:32:07)  [7]

    вызвал OnTerminate, поток уничтожился
  • Anatoly Podgoretsky © (26.09.11 21:11) [11]
    > FireMan_Alexey  (26.09.2011 01:20:08)  [8]

    ProcessMessages минимум замедляет выполнение программы всего лишь на
    несколько наносекунд.
  • FireMan_Alexey © (27.09.11 01:31) [12]
    > Anatoly Podgoretsky ©

    Я проверял при просчете алгоритмов пересечения плоскостей с вектором, при отсутствии в цикле ProcessMessages ~170000 тыс плоскостей в секунду, с ProcessMessages ~120000 тыс. плоск/сек.
  • Anatoly Podgoretsky © (27.09.11 06:22) [13]
    > FireMan_Alexey  (27.09.2011 01:31:12)  [12]

    У тебя наверно много чего в ProcessMessages, например перерисовка
    интерфейса.
  • sniknik © (27.09.11 09:19) [14]
    > Я проверял
    как проверял? код.
    ProcessMessages сам ничего не занимает, но он дает возможность обработки событий (даже по названию) и если ты их там в цикле инициализируешь (ну вот "просчет" у тебя наверняка не просто считает а еще и рисует?)... то считаешь ты время их исполнения, а не время ProcessMessages. а без него в цикле событие выполнилось 1 раз, сколько бы ты там в цикле изменений не сделал.
  • FireMan_Alexey © (27.09.11 12:11) [15]
    > sniknik ©

    T:=GetTickCount;
    I:=0;
    While T+1000>GetTickCount do
     Begin
        ...
        Inc(I);
     End;



    Прорисовки просчетов не было. Одна кнопка. Кол-во выводилось ShowMessage- ом. Когда тестил, хотел узнать сколько мой 1,4ГГц проц сможет посчитать плоскостей в пространстве...
    Вычисления были с синусами/косинусами, возможно это повлияло, спорить не буду, но как мне показалось, все таки изменения в скорости данная процедура дает(ИМХО)
  • Cobalt © (27.09.11 15:56) [16]
    Тут немаловажное значение имеет частота вызова ProcessMessages.
    Если идет обработка миллиона элементов, то вызов после обработки каждого элемента неблагоразумен.
    Вполне разумно при обработке больших данных вызывать этот метод раз в полсекунды.
    GetTickcount в помощь.
  • Eraser © (27.09.11 16:32) [17]
    > [15] FireMan_Alexey ©   (27.09.11 12:11)


    > Прорисовки просчетов не было. Одна кнопка. Кол-во выводилось
    > ShowMessage- ом.

    это не очень хорошая практика. лучше, в данном случае, всю операцию производить в потоке, а состояние выполнение обновлять в GUI по таймеру, например, раз в секунду. так же не забывать про защиту критической секцией.
  • sniknik © (27.09.11 17:41) [18]
    > все таки изменения в скорости данная процедура дает(ИМХО)
    но считаешь то ты не скорость... количество циклов за промежуток времени.

    вот скорость
    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;
       //Application.ProcessMessages;

     Edit2.Text:= IntToStr(GetTickCount - T);
    end;



    0 сек на 100000 в обоих случаях, а вот 1000000 уже (на моем компе) 31 тик в первом случае и тот же 0 во втором т.е. 31/1000 секунды на 1000000  итераций т.е. 0,031/1000000 секунды для 1го "чистого" Application.ProcessMessages;.

    > Если идет обработка миллиона элементов
    ну вон для миллиона = 0,031 сек. критично? в отличие от если идет перерисовка, то этом миллион может на час растянутся к примеру.
  • FireMan_Alexey © (27.09.11 21:13) [19]
    >sniknik ©
    Я же говорил, что считаю кол-во пересечений с плоскостями :), смотри [12] ;)
    Я не возражаю, что возможно на твоем проце ProcessMessages выполняется за такой промежуток времени/тиков, я лишь проводил эксперимент для себя и сделал для СЕБЯ вывод, что задержка все-таки существует, а если добавить еще и прорисовку, то время задержки увеличиться... :)
    Админ - прости, что отклонились от темы топик стартера!
  • sniknik © (27.09.11 22:08) [20]
    > что возможно на твоем проце ProcessMessages выполняется за такой промежуток времени/тиков
    не у меня, а вообще. у всех.
    ну или по крайней мере у двоих... с чего начали -
    Anatoly Podgoretsky ©   (26.09.11 21:11) [11]
    > ProcessMessages минимум замедляет выполнение программы всего лишь на несколько наносекунд.
    ты зачем то начал возражать, но привел замеры тиков в секунду... что в общем то ничем, в пересчете на скорость выполнения самого ProcessMessages, от "несколько наносекунд" не отличается. хотя естественно выглядит солиднее - "а в попугаях то я значительно длиннее".

    > Админ - прости, что отклонились от темы топик стартера!
    АП (Anatoly Podgoretsky) добрый, считай уже простил. ;)
  • имя (12.07.12 23:31) [21]
    Удалено модератором
 
Конференция "Сети" » Подвисание приложения при передаче письма через TIdSMTP [D7, WinXP]
Есть новые Нет новых   [134435   +18][b:0][p:0.001]