Форум: "Начинающим";
Текущий архив: 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