Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.03.2012, 08:05   #1
bagabuga
Пользователь
 
Регистрация: 27.11.2010
Сообщений: 18
Вопрос Поток (Thread) не хочет показывать панель (Panel).

Здравствуйте!
Вообщем имеется вот такой код потока:

Код:
procedure TThreadViewMailRu.Execute;
var HTTPSend : THTTPSend;
    html : TStringList;
    data : TStringStream;
    box : string;
begin
 try
  try
   Synchronize(
      procedure
      begin
        with FormAddEmail do
        begin
         F2_EditEmail.Enabled:=False;
         F2_ComboBoxDomain.Enabled:=False;
         F2_EditPass.Enabled:=False;
         F2_ButtonOk.Enabled:=False;
         F2_ButtonCancel.Enabled:=False;
        end;
       FormMain.StatusBar.SimpleText:='Авторизация на сервере Mail.Ru...';
      end
    );

   httpsend := THTTPSend.Create;
   html := TStringList.Create;
   data := TStringStream.Create;

   FormMain.ListBoxViewMail.Clear;
   LinkViewEmail.Clear;

   with httpsend do
   begin
    TargetHost:='m.mail.ru';
    TargetPort:='80';
    Protocol:='1.1';
    UserAgent:='Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
    MimeType:='application/x-www-form-urlencoded';
   end;

   data.WriteString('page=http://m.mail.ru/cgi-bin/folders&');
   data.WriteString('Page=http://m.mail.ru/cgi-bin/folders&');
   data.WriteString('FailPage=http://m.mail.ru/cgi-bin/login?fail=1&');
   data.WriteString('post=&');
   data.WriteString('login_from=&');
   data.WriteString('Login=' + FormAddEmail.F2_EditEmail.Text + '&');
   data.WriteString('Domain=' + FormAddEmail.F2_ComboBoxDomain.Text + '&');
   data.WriteString('Password=' + FormAddEmail.F2_EditPass.Text);

   HttpSend.Document.LoadFromStream(data);
   HttpSend.HTTPMethod('POST', 'http://m.mail.ru/cgi-bin/auth');
   html.Text := HTTPSend.Headers.Text;

   httpsend.Headers.Clear;
   httpsend.Document.Clear;

   Synchronize(
      procedure
      begin
        FormMain.StatusBar.SimpleText:='Парсинг входящих...'
      end
    );

   if Pos('http://m.mail.ru/cgi-bin/folders', html.Text) <> 0 then
    begin
     HTTPSend.Cookies.SaveToFile('cookie.txt');
     httpsend.HTTPMethod('GET', 'http://m.mail.ru/cgi-bin/msglist');
     html.LoadFromStream(httpsend.Document);
     html.Text:=Utf8ToAnsi(html.Text);
     repeat
      box := FormMain.Pars('class="box">', html.Text, '</td>');
      FormMain.ListBoxViewMail.Items.Add(trim(FormMain.Pars('author">', box, '</span>')) + ' | ' 
+ 'Тема: ' + trim(FormMain.Pars('theme">', box, '</span>')));
      LinkViewEmail.Add('http://m.mail.ru/cgi-bin/' + FormMain.Pars('href="', box, '"'));
      box := html.Text;
      Delete(box, 1, Pos('class="box">', box) + 15);
      html.Text:= box;
     until(Pos('class="box">', html.Text) = 0);
    end;

    Synchronize(
      procedure
      begin
       with FormMain do
       begin
        StatusBar.SimpleText:='Готово!';
        //PanelRegistrationEmail.Visible:=False;
        PanelViewMail.Visible:=True;
       end;

       with FormAddEmail do
       begin
        F2_EditEmail.Clear;
        F2_ComboBoxDomain.ItemIndex:=0;
        F2_EditPass.Clear;

        F2_EditEmail.Enabled:=True;
        F2_ComboBoxDomain.Enabled:=True;
        F2_EditPass.Enabled:=True;
        F2_ButtonOk.Enabled:=True;
        F2_ButtonCancel.Enabled:=True;

        Close;
       end;
      end
    );
  finally
   httpsend.Free;
   html.Free;
   data.Free;
  end;
 except

 end;
end;
Здесь происходит авторизация на Mail.Ru через synapse, затем идет парсинг входящих с выводом в listbox. Все прекрасно если бы не полнейшее зависание формы после
Код:
PanelViewMail.Visible:=True;
, пробовал так же с другой панелью, все равно зависает. Нашел в гугле пару тем, там тоже писали что при выставлении у компонентов свойства visible в true (в потоке) форма виснет, но решения проблемы не было. Может подскажете что нибудь? Это как нибудь решается или есть альтернатива? В панели располагается непосредственно сам listbox, groupbox и два label'a. Заранее спасибо!
P.S. Delphi XE2

Последний раз редактировалось rpy3uH; 30.03.2012 в 15:20.
bagabuga вне форума Ответить с цитированием
Старый 30.03.2012, 09:39   #2
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Гм, я в недоумении: по какому принципу вы делите код на код, нуждающийся в синхронизации, и не нуждающийся в ней? Почему простейшие действия вроде изменения Enabled вы заворачиваете в Synchronize, а тяжеловесы вроде FormMain.ListBoxViewMail.Clear или FormMain.ListBoxViewMail.Items.Add - нет?

Из вторичного потока НЕЛЬЗЯ обращаться к визуальным компонентам. Поэтому, заворачивайте в Synchronize любой код, который обращается к формам и компонентам на ней.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 30.03.2012, 09:44   #3
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Я вообще изменил бы логику работы.

Код:
 with FormAddEmail do
        begin
         F2_EditEmail.Enabled:=False;
         F2_ComboBoxDomain.Enabled:=False;
         F2_EditPass.Enabled:=False;
         F2_ButtonOk.Enabled:=False;
         F2_ButtonCancel.Enabled:=False;
        end;
       FormMain.StatusBar.SimpleText:='Авторизация на сервере Mail.Ru...';
это может делать сама форма перед запуском потока.

Код:
   with FormMain do
       begin
        StatusBar.SimpleText:='Готово!';
        //PanelRegistrationEmail.Visible:=False;
        PanelViewMail.Visible:=True;
       end;

       with FormAddEmail do
       begin
        F2_EditEmail.Clear;
        F2_ComboBoxDomain.ItemIndex:=0;
        F2_EditPass.Clear;

        F2_EditEmail.Enabled:=True;
        F2_ComboBoxDomain.Enabled:=True;
        F2_EditPass.Enabled:=True;
        F2_ButtonOk.Enabled:=True;
        F2_ButtonCancel.Enabled:=True;

        Close;
       end;
это, опять же, может делать и сама форма после окончания работы потока. К примеру, можно назначить событие OnTerminate.

Код:
     FormMain.StatusBar.SimpleText:='Парсинг входящих...'
поток может направить сообщение-уведомление форме. Она среагирует и изменит статус.

Цитата:
FormMain.ListBoxViewMail.Items.Add( trim(FormMain.Pars('author">', box, '</span>')) + ' | ' + 'Тема: ' + trim(FormMain.Pars('theme">', box, '</span>')));
LinkViewEmail.Add('http://m.mail.ru/cgi-bin/' + FormMain.Pars('href="', box, '"'));
box := html.Text;
аналогично.

Иными словами, поток вообще не должен ссылаться на форму. Почитайте: http://www.gunsmoker.ru/2010/08/9897.html
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 30.03.2012, 10:13   #4
bagabuga
Пользователь
 
Регистрация: 27.11.2010
Сообщений: 18
По умолчанию

GunSmoker, Я Synchronize вообще не использовал и без него прекрасно работает, ведь поток у меня один, а Synchronize нужен для синхронизации нескольких (вроде бы). Где-то прочитал, что весь код касаемо основной формы должен обрабатываться через Synchronize, подумал может мне это поможет, но увы. Сейчас вынесу все за пределы потока, т.е. перепишу код . Просто с потоками вообще не имел дело, а тут не дело же что все виснет, решил попробовать.
bagabuga вне форума Ответить с цитированием
Старый 30.03.2012, 10:34   #5
RuVarez
Форумчанин
 
Аватар для RuVarez
 
Регистрация: 25.08.2010
Сообщений: 258
По умолчанию

Synchronize используется и для синхронизации с компонента! Видите ли, потоки плоховато работают с VCL поэтому нужно использовать Synchronize. Не верите -
напишите в Execute потока Showmessage и не ставте Synchronize и он вам будет так извращатся над тем Showmessage)
RuVarez вне форума Ответить с цитированием
Старый 30.03.2012, 12:26   #6
bagabuga
Пользователь
 
Регистрация: 27.11.2010
Сообщений: 18
По умолчанию

Цитата:
Сообщение от RuVarez Посмотреть сообщение
Synchronize используется и для синхронизации с компонента! Видите ли, потоки плоховато работают с VCL поэтому нужно использовать Synchronize. Не верите -
напишите в Execute потока Showmessage и не ставте Synchronize и он вам будет так извращатся над тем Showmessage)
Было дело, писал . Поток растянул форму на весь экран, в итоге ни сообщения, ни кнопок видно не было.


Итак, вообщем я попытался вытащить весь код что обращается к форме из потока, получилось следующее:
Код потока:
Код:
procedure TThreadViewMailRu.Execute;
var HTTPSend : THTTPSend;
    html : TStringList;
    data : TStringStream;
    box : string;
begin
 try
  try
   httpsend := THTTPSend.Create;
   html := TStringList.Create;
   data := TStringStream.Create;

   with httpsend do
   begin
    TargetHost:='m.mail.ru';
    TargetPort:='80';
    Protocol:='1.1';
    UserAgent:='Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
    MimeType:='application/x-www-form-urlencoded';
   end;

   data.WriteString('page=http://m.mail.ru/cgi-bin/folders&');
   data.WriteString('Page=http://m.mail.ru/cgi-bin/folders&');
   data.WriteString('FailPage=http://m.mail.ru/cgi-bin/login?fail=1&');
   data.WriteString('post=&');
   data.WriteString('login_from=&');
   data.WriteString('Login=' + FormAddEmail.F2_EditEmail.Text + '&');
   data.WriteString('Domain=' + FormAddEmail.F2_ComboBoxDomain.Text + '&');
   data.WriteString('Password=' + FormAddEmail.F2_EditPass.Text);

   HttpSend.Document.LoadFromStream(data);
   HttpSend.HTTPMethod('POST', 'http://m.mail.ru/cgi-bin/auth');
   html.Text := HTTPSend.Headers.Text;

   httpsend.Headers.Clear;
   httpsend.Document.Clear;

   Synchronize(
      procedure
      begin
        FormMain.StatusBar.SimpleText:='Парсинг входящих...'
      end
   );

   if Pos('http://m.mail.ru/cgi-bin/folders', html.Text) <> 0 then
    begin
     HTTPSend.Cookies.SaveToFile('cookie.txt');
     httpsend.HTTPMethod('GET', 'http://m.mail.ru/cgi-bin/msglist');
     html.LoadFromStream(httpsend.Document);
     html.Text:=Utf8ToAnsi(html.Text);

     Synchronize(
       procedure
        begin
         repeat
          box := FormMain.Pars('class="box">', html.Text, '</td>');
          FormMain.ListBoxViewMail.Items.Add(
Copy(FormMain.HtmlSpecialChars(trim(FormMain.Pars('author">', box, '</span>'))), 1, 25) 
+ ' | ' + 'Тема: ' + trim(FormMain.Pars('theme">', box, '</span>')));
          LinkViewEmail.Add('http://m.mail.ru/cgi-bin/' + FormMain.Pars('href="', box, '"'));
          box := html.Text;
          Delete(box, 1, Pos('class="box">', box) + 15);
          html.Text:= box;
         until(Pos('class="box">', html.Text) = 0);
        end
     );
    end
  finally
   httpsend.Free;
   html.Free;
   data.Free;
  end;
 except

 end;
end;
Кнопка:
Код:
procedure TFormAddEmail.F2_ButtonOkClick(Sender: TObject);
var Thread : TThreadViewMailRu;
begin
 F2_EditEmail.Enabled:=False;
 F2_ComboBoxDomain.Enabled:=False;
 F2_EditPass.Enabled:=False;
 F2_ButtonOk.Enabled:=False;
 F2_ButtonCancel.Enabled:=False;

 FormMain.StatusBar.SimpleText:='Авторизация на сервере Mail.Ru...';
 FormMain.ListBoxViewMail.Clear;
 LinkViewEmail.Clear;


 Thread:=TThreadViewMailRu.Create(True);
 Thread.FreeOnTerminate:=True;
 Thread.OnTerminate:= DestroyThread;
 Thread.Resume;
end;
DestroyThread:
Код:
procedure TFormAddEmail.DestroyThread(Sender: TObject);
begin
 with FormMain do
  begin
   StatusBar.SimpleText:='Готово!';
   PanelRegistrationEmail.Visible:=False;
   PanelViewMail.Visible:=True;
  end;

  FormMain.labelViewMail.Caption:='E-Mail: ' + F2_EditEmail.Text + '@' + F2_ComboBoxDomain.Text;
  FormMain.LabelViewInbox.Caption:='Входящие: ' + IntToStr(FormMain.ListBoxViewMail.Count);


  F2_EditEmail.Clear;
  F2_ComboBoxDomain.ItemIndex:=0;
  F2_EditPass.Clear;

  F2_EditEmail.Enabled:=True;
  F2_ComboBoxDomain.Enabled:=True;
  F2_EditPass.Enabled:=True;
  F2_ButtonOk.Enabled:=True;
  F2_ButtonCancel.Enabled:=True;

  Close;
end;
Что касается "направить сообщение-уведомление форме" как это реализуется не знаю, информации особо тоже не нашел. Как вытащить цикл тоже не представляю, это либо делать html глобальной (что вроде как не вариант), либо сохранять в файл, затем создавать ещё один TStringList туда подгружать html код из файла (Тоже геморрой). Что подскажите?

Последний раз редактировалось rpy3uH; 30.03.2012 в 15:21.
bagabuga вне форума Ответить с цитированием
Старый 30.03.2012, 12:30   #7
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Тебе поток, по сути, нужен, чтобы не подвисал интерфейс программы во время вызова GET. А раз так, то глянь сюда: http://www.delphikingdom.ru/asp/view...catalogid=1355

У тебя будет:
Код:
  ...
  EnterWorkerThread;
  try
    httpsend.HTTPMethod('GET', 'http://m.mail.ru/cgi-bin/msglist');
  finally
    LeaveWorkerThread;
  end;
  ...
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 30.03.2012, 14:57   #8
bagabuga
Пользователь
 
Регистрация: 27.11.2010
Сообщений: 18
По умолчанию

Цитата:
Сообщение от GunSmoker Посмотреть сообщение
Тебе поток, по сути, нужен, чтобы не подвисал интерфейс программы во время вызова GET. А раз так, то глянь сюда: http://www.delphikingdom.ru/asp/view...catalogid=1355

У тебя будет:
Код:
  ...
  EnterWorkerThread;
  try
    httpsend.HTTPMethod('GET', 'http://m.mail.ru/cgi-bin/msglist');
  finally
    LeaveWorkerThread;
  end;
  ...
Огромное спасибо! Это то, что нужно.
bagabuga вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Динамичная панель - Можно ли сделать так чтобы панель или любой элемент, выдвигались при наведении IHaveQuestions Компоненты Delphi 7 30.11.2011 09:49
Поток. Не получается создать поток. Выдает ошибки при запуске bigory Общие вопросы по Java, Java SE, Kotlin 3 23.09.2010 00:40
Thread.Приложение не отвечает. Не запускается поток. Zerofill Общие вопросы Delphi 2 10.10.2009 16:04
Показывать-не показывать скрытые файлы и папки... Романнн Свободное общение 5 07.11.2007 13:16