Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.03.29;
Скачать: [xml.tar.bz2];

Вниз

Организация работы потоков   Найти похожие ветки 

 
Тимоха   (2009-02-03 00:58) [80]

Спасибо! что плохого в Self?


 
Тимоха   (2009-02-03 01:01) [81]

вмысле без него))))))))


 
Тимоха   (2009-02-03 05:25) [82]

Передаю record через указатель.
 try
   mess := PRecord(message.LParam);
   mmo1.lines.Add("Имя: " + mess.name + ", Тема: " + mess.tema);
 finally
   Dispose(mess);
 end;


Результат:

Имя: koha!, Тема: Вопрос по функции API Openfile()
Имя: Тимоха, Тема: Организация работы потоков
Имя: mr.devil, Тема: Задание кодировки для xml
Имя: CodeMaster, Тема: Отключение скроллбаров
Имя: killaTank, Тема: Создание базы (Db) с помошью Delphi
Имя: cruiser, Тема: WinInet и закачка файла из Интернет через прокси с авторизацией.


 
Тимоха   (2009-02-03 06:27) [83]

Возникли вопросы по поводу памяти,

 repeat
   New(mess); // выделяю память
   count_name := PosEx("", page, index_name);
   count_tema := PosEx("</a>", page, index_tema);
   mess.tema := Copy(page, index_tema + 7, count_tema - index_tema - 7);
   mess.name := Copy(page, index_name + 9, count_name - index_name - 9);
   SendMessage(hwnd, wm_buf, 0, Integer(mess));
   index_name := PosEx("<nobr>", page, count_name);
   index_tema := PosEx("&n=18">", page, count_tema);
 until index_name = 0;

try
  mess := PRecord(message.LParam);
  mmo1.lines.Add("Имя: " + mess.name + ", Тема: " + mess.tema);
finally
  Dispose(mess);  удаляю
end;


верно ли будет такая реализация с памятью?


 
Сергей М. ©   (2009-02-03 08:18) [84]


> что плохого в Self?


Ничего плохого.
Но ты же ведь не понимаешь, зачем тут этот Self, раз написал его ..
Какой смысл лезть в дебри, если нет понимания основ ?


> верно ли будет такая реализация с памятью?
>


Где, в каком месте кода все это происходит ?


 
Сергей М. ©   (2009-02-03 08:24) [85]

И чем не устраивает вариант с обработкой OnTerminate ?


 
Тимоха   (2009-02-03 19:57) [86]

Это в execute рабочего треда:

repeat
  New(mess); // выделяю память
  count_name := PosEx("", page, index_name);
  count_tema := PosEx("</a>", page, index_tema);
  mess.tema := Copy(page, index_tema + 7, count_tema - index_tema - 7);
  mess.name := Copy(page, index_name + 9, count_name - index_name - 9);
  SendMessage(hwnd, wm_buf, 0, Integer(mess));
  index_name := PosEx("<nobr>", page, count_name);
  index_tema := PosEx("&n=18">", page, count_tema);
until index_name = 0;


Это в мэйнтреде:
try
 mess := PRecord(message.LParam);
 mmo1.lines.Add("Имя: " + mess.name + ", Тема: " + mess.tema);
finally
 Dispose(mess);  удаляю
end;


 
Сергей М. ©   (2009-02-03 20:12) [87]


> Тимоха   (03.02.09 19:57) [86]


Что ты как попугай заладил одно и то же ?)

На [85] ответь)..


 
Тимоха   (2009-02-03 20:14) [88]

Меня все устраивает, я хочу сделать оба варианта. И понять какой лучше.


 
Сергей М. ©   (2009-02-03 20:23) [89]

Ясно)


 
Тимоха   (2009-02-03 20:32) [90]

Для OnTerminate:
делаю  

...
procedure HandleOnTerminate(Sender:TObject);
...

MyThread:= TTest.create("http://www.delphimaster.ru/cgi-bin/forum.pl?n=18");
MyThread.OnTerminate := HandleOnTerminate;

Не понимаю как будут передаваться данные в этом случае? Как поток отработает, наступает OnTerminate, тут то мы и должны данные где то хранить (в буфере?), вытаскиваем из буфера и все тип-топ. Так должен выглядеть алгоритм?


 
Медвежонок Пятачок ©   (2009-02-03 20:46) [91]

в онтерминате обработчике нитка еше жива.
и живы свойства нитки


 
Тимоха   (2009-02-03 20:50) [92]

Спасибо!
Т.е. в рабочем треде нужно создать property в него записывать данные

а при onterminate
в procedure HandleOnTerminate(Sender:TObject);

обращаться к потоку к заданному property и вытаскивать оттуда данные?


 
Тимоха   (2009-02-03 21:43) [93]

Сделал так:
В рабочем треде создаю TList,List_count.

   try
     New(mess);
     List.Add(mess);
     Inc(List_count);
     mess.tema := Copy(page, index_tema + 7, count_tema - index_tema - 7);
     mess.name := Copy(page, index_name + 9, count_name - index_name - 9);
   finally
   end;


в HandleOnTerminate в мэйнтреде:

 try
   for i := 0 to potok.List_count - 1 do
   begin
     mess := potok.List.Items[i];
     mmo1.Lines.Add("Имя: " + mess.name + ", Тема: " + mess.tema);
   end;
 finally
   Dispose(mess);
 end;


При таком варианте утечки памяти не будет?


 
Тимоха   (2009-02-04 00:26) [94]

Объясните пожалуйста что использовать лучше и почему? sendmessage или onterminate для получения данных с треда?


 
Медвежонок Пятачок ©   (2009-02-04 00:41) [95]

это вопрос мировоззрения и вкуса


 
Eraser ©   (2009-02-04 01:00) [96]

> [93] Тимоха   (03.02.09 21:43)


> При таком варианте утечки памяти не будет?

нужно запомнить одно золотое правило - память надо освобождать там же, где и выделять... по возможности.
если сейчас есть уверенность в том, что окно, которому предназначается сообщение существует, то ситуация со временем может поменяться, а код останется.
есть два варианта.
1.

  New(mess);
  try
    // send message
  finally
    Dispose(mess);
  end;

предпочтительный:
выделять память для сообщения в стеке.


 
Тимоха   (2009-02-04 01:01) [97]

А если рассматривать с точки зрения что потом я собираюсь синхронизировать треды?


 
Eraser ©   (2009-02-04 01:04) [98]

> [94] Тимоха   (04.02.09 00:26)


> Объясните пожалуйста что использовать лучше и почему?

лучше почитать матчасть, вот что лучше. т.е. разобраться, что такое sendmessage и что такое onterminate. тогда и таких вопросов задавать не будешь.


 
Riply ©   (2009-02-04 01:21) [99]

> [93] Тимоха   (03.02.09 21:43)

Что-то я не поняла: ты сколько раз выделяешь память и сколько раз освобождаешь ?
И зачем введена переменная List_count ?


 
Тимоха   (2009-02-04 01:30) [100]

List_count не нужен. Облажался.


 
Тимоха   (2009-02-04 04:36) [101]

Тред собирает все имена авторов тем с форума (начинающим).
Теперь нужно чтобы он работал через каждые скажем 5 мин и проверял, если есть новые то добавляем в список, если нет то ниче не делаем.
Каков алгоритм?
Я представляю это себе так, есть таймер и есть булевая переменная, которая отвечает за то какой раз запустился тред. В таймере проверяем если поток уже запускался, то теперь через каждые 5 мин запускаем его снова. Ну и сделать какую то переменную, которая отвечала за то работает в данный момент поток или нет.


 
Riply ©   (2009-02-04 04:59) [102]

> [101] Тимоха   (04.02.09 04:36)
> Каков алгоритм?

Ты не ответил на мой первый вопрос в [99]


 
Тимоха   (2009-02-04 05:58) [103]


> Ты не ответил на мой первый вопрос в [99]

Выделяю и освобождаю ровно столько, сколько записей передаю


 
Сергей М. ©   (2009-02-04 09:15) [104]


> если рассматривать с точки зрения что потом я собираюсь
> синхронизировать треды?


И событие OnTerminate и синхронная отправка/получение оконного сообщения есть событие синхронизации.


 
Riply ©   (2009-02-04 10:18) [105]

> [103] Тимоха   (04.02.09 05:58)
> Выделяю и освобождаю ровно столько, сколько записей передаю

Конечно, сложно судить по вырванным кусочкам,
но из кода, приведенного, в [93] я не вижу этого.


 
Тимоха   (2009-02-04 11:12) [106]

procedure TForm1.btn1Click(Sender: TObject);
begin
 potok := TTest.create(form1.Handle, "http://www.delphimaster.ru/cgi-bin/forum.pl?n=18", wm_buf);
end;

procedure TForm1.handlenewdata(var message: TMessage);
var mess: PRecord;
begin
 try
   mess := Pointer(message.LParam);
   if listbox1.Items.IndexOf(mess^.name) = -1 then
   begin
     ListBox1.Items.Add(mess^.name);
   end;
   Dispose(mess);
 except
   ShowMessage("Error!");
 end;

end;

type
 PRecord = ^TRecord;
 TRecord = record
   name: string[50];
   tema: string[150];
 end;

type
 TTest = class(TThread)
 private
   http: tidhttp;
   page: string;
   FUrl: string;
   hwnd: THandle;
   FMsg: Integer;
 protected
   procedure Execute; override;
 public
   constructor Create(h: THandle; Url: string;aMsg:Integer); overload;
   destructor Destroy; override;
 end;

implementation

constructor TTest.Create(h: THandle; Url: string; aMsg:Integer);
begin
 inherited Create(True);
 FUrl := url;
 hwnd := h;
 FMsg := aMsg;
 http := TIdHTTP.Create(nil);
 Priority := tpNormal;
 FreeOnTerminate := true;
 Resume;
end;

destructor TTest.destroy;
begin
 http.Free;
 inherited;
end;

procedure TTest.Execute;
var
 index_name, count_name: Integer;
 index_tema, count_tema: Integer;
 mess: PRecord;
begin
 page := http.Get(FUrl);
 index_tema := 0;
 index_name := 0;
 count_name := 0;
 count_tema := 0;
 index_tema := PosEx("&n=18">", page, count_tema);
 index_name := PosEx("<nobr>", page, count_name);
 repeat
   count_name := PosEx("
", page, index_name);
   count_tema := PosEx("</a>", page, index_tema);
   try
     New(mess);
     mess^.tema := Copy(page, index_tema + 7, count_tema - index_tema - 7);
     mess^.name := Copy(page, index_name + 9, count_name - index_name - 9);
     PostMessage(hwnd, FMsg, 0, Integer(mess));
     Sleep(1);
   finally
   end;
   index_name := PosEx("<nobr>", page, count_name);
   index_tema := PosEx("&n=18">", page, count_tema);
 until index_name = 0;
end;


 
Тимоха   (2009-02-04 11:19) [107]

sleep не туда засунул


 
Сергей М. ©   (2009-02-04 11:23) [108]


> sleep не туда засунул


Оттого, видимо, и не выходит каменный цветок ?)
Причем здесь слип ? Кому он интересен кроме тебя ? Ты же о синхронизации сейчас печешься, а не о "тормозах"..


 
Тимоха   (2009-02-04 11:27) [109]

на мой [101] никто не ответил


 
Медвежонок Пятачок ©   (2009-02-04 11:30) [110]

В таймере проверяем если поток уже запускался, то теперь через каждые 5 мин запускаем его снова.

то есть ни один поток после старта программы не будет запущен никогда.


 
Тимоха   (2009-02-04 11:31) [111]

почему же, нажимаем на кнопку и пошел.


 
Сергей М. ©   (2009-02-04 11:35) [112]


> Тимоха   (04.02.09 11:27) [109]


Так.
И что с чем синхронизировать при этом надо ?


 
Медвежонок Пятачок ©   (2009-02-04 11:35) [113]

таймер здесь плохой помощник.

допустим, что за секунду до его тика очередной поток завершился, и выставил флаг "я уже запускался".
и не успел он как следует передохнуть, как таймер пошлет его на делфимастер снова.


 
Тимоха   (2009-02-04 11:44) [114]

Сергей М, допустим будет еще один поток, который будет делать тоже самое что и первый, но только с другой конференции и проверять есть ли там вопросы какого нить автора из 20-ки с конференции для начинающих, есть есть, то в листбоксе он должен как то отметится. А первый в это время проверяет появились ли новые и добавляет их в список, если из 20-ки автор выбыл, то его из списка удаляем даже если он есть в другой конференции. Типо того.
Медвежонок Пятачок, как решить?


 
Медвежонок Пятачок ©   (2009-02-04 11:47) [115]

поток при завершении должен либо сам записать в структуру, ассоциированную с его конференцией время следующего старта, либо за него это должен сделать главный поток (Now + Delta).
В таймере смотреть, не превышет ли текущее время время следующего запуска очередного потока. Если превышает, то стартовать.
Булеву переменную убрать.


 
Тимоха   (2009-02-05 03:42) [116]

Спасибо! Вот код двух юнитов, взгляните пожалуйста и скажите что конкретно в коде не правильно:
Следующие разы поток не запускается, мне кажется что он неправильно освобождается.
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls;

const
 wm_buf = wm_app + 1234;

type
 TForm1 = class(TForm)
   btn1: TButton;
   ListBox1: TListBox;
   ListBox2: TListBox;
   Timer1: TTimer;
   Button1: TButton;
   procedure btn1Click(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
   procedure FormCreate(Sender: TObject);
 private
   procedure handleonterminate(sender: TObject);
   procedure handlenewdata(var message: TMessage); message wm_buf;
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 Time_end, delta: TDateTime;
implementation

uses Unit2;

{$R *.dfm}
var
 potok: TTest;

procedure TForm1.btn1Click(Sender: TObject);
begin
 potok := TTest.create(form1.Handle, "http://www.delphimaster.ru/cgi-bin/forum.pl?n=18", wm_buf);
 potok.OnTerminate := handleonterminate;
end;

procedure TForm1.handlenewdata(var message: TMessage);
var mess: PRecord;
begin
 try
   mess := Pointer(message.LParam);
   if listbox1.Items.IndexOf(mess^.name) = -1 then
     ListBox1.Items.Add(mess^.name);
   Dispose(mess);
 except
   //
 end;

end;

procedure TForm1.handleonterminate(sender: TObject);
begin
 Time_end := Now + Delta;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 if Time_end <> 0 then
   if (Now >= Time_end) and not Assigned(potok) then
     potok := TTest.create(form1.Handle, "http://www.delphimaster.ru/cgi-bin/forum.pl?n=18", wm_buf);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Time_end := StrToTime("00:00:00");
 delta := StrToTime("00:00:05");
end;

end.

unit Unit2;

interface

uses
 Classes, idhttp, unit1, StrUtils, windows, SysUtils;

type
 PRecord = ^TRecord;
 TRecord = record
   name: string[50];
   tema: string[150];
 end;

type
 TTest = class(TThread)
 private
   http: tidhttp;
   page: string;
   FUrl: string;
   hwnd: THandle;
   FMsg: Integer;
 protected
   procedure Execute; override;
   procedure PostRecord(Rec:PRecord);
 public
   constructor Create(h: THandle; Url: string;aMsg:Integer); overload;
   destructor Destroy; override;
 end;

implementation

constructor TTest.Create(h: THandle; Url: string; aMsg:Integer);
begin
 inherited Create(True);
 FUrl := url;
 hwnd := h;
 FMsg := aMsg;
 http := TIdHTTP.Create(nil);
 Priority := tpNormal;
 FreeOnTerminate := True;
 Resume;
end;

destructor TTest.destroy;
begin
 http.Free;
 inherited;
end;

procedure TTest.Execute;
var
 index_name, count_name: Integer;
 index_tema, count_tema: Integer;
 mess: PRecord;
begin
 page := http.Get(FUrl);
 index_tema := 0;
 index_name := 0;
 count_name := 0;
 count_tema := 0;
 index_tema := PosEx("&n=18">", page, count_tema);
 index_name := PosEx("<nobr>", page, count_name);
 repeat
   count_name := PosEx("
", page, index_name);
   count_tema := PosEx("</a>", page, index_tema);
   try
     Sleep(1);
     New(mess);
     mess^.tema := Copy(page, index_tema + 7, count_tema - index_tema - 7);
     mess^.name := Copy(page, index_name + 9, count_name - index_name - 9);
     PostRecord(mess);
   finally
   end;
   index_name := PosEx("<nobr>", page, count_name);
   index_tema := PosEx("&n=18">", page, count_tema);
 until index_name = 0;
end;

procedure TTest.PostRecord(Rec: PRecord);
begin
 PostMessage(hwnd, FMsg, 0, Integer(Rec));
end;

end.


 
Тимоха   (2009-02-05 11:50) [117]

Допустим у меня поток не прекращает работу на протяжении работы все программы, и завершается при application.terminate
Если я добавлю еще один поток, который будет тоже посылать сообщение, а на форме будет обрабатывать и обращаться к listbox. В таком случае не будет некорректных данных?



Страницы: 1 2 3 вся ветка

Форум: "Начинающим";
Текущий архив: 2009.03.29;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.68 MB
Время: 0.053 c
4-1207116283
kudatsky
2008-04-02 10:04
2009.03.29
О функции SHFileOperation


2-1233121683
Vemer
2009-01-28 08:48
2009.03.29
Записать-прочитать файл под WinApi


2-1233240872
Fonts
2009-01-29 17:54
2009.03.29
Про фонты дисплея


15-1232942877
Дмитрий С
2009-01-26 07:07
2009.03.29
Номер версии в InnoSetup


9-1177753114
pavel_guzhanov
2007-04-28 13:38
2009.03.29
Стоит ли читать книгу Краснова





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский