Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.03.29;
Скачать: CL | DM;

Вниз

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

 
Тимоха   (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;
Скачать: CL | DM;

Наверх




Память: 0.7 MB
Время: 0.023 c
2-1233804054
snake-as
2009-02-05 06:20
2009.03.29
При открытии файла через OpenDialog имя файла не сохраняется


3-1217236001
JanMihail
2008-07-28 13:06
2009.03.29
Создание отчета в Delphi???


2-1234175488
TTLr
2009-02-09 13:31
2009.03.29
Сортировка данных по 2-м полям


2-1233414166
SkyN
2009-01-31 18:02
2009.03.29
получить содержимое и нажать кнопку страницы открытой в браузере


2-1234175149
b@v
2009-02-09 13:25
2009.03.29
Отчет