![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Организация работы потоков
Тимоха © (2009-02-02 08:20:00)Написал программу, которая выполняет ряд некоторых функций.
Одни из которых это - связь с сайтом и получение от него определенной информации, анализ полученной информации, проверка наличия новых данных на том же сайте и их загрузка.
Необходимо реализовать работу функций программы с использованием потоков.
Более подробное описание задачи потоков:
При старте программы возможны два варианта:
(А).Программа запускается впервые,поэтому запускается поток ThrStartFirst. Этот поток скачивает с сайта страницу, парсит нужные данные и добавляет их в более расширенный компонент listbox(у листбокса есть свойства text,text1,text2,text3). В то время как работает ThrStartFirst, запускается следующий поток ThrStratAnalys, который берет по очереди каждый итем листбокса, вытаскивает свойство text и скачивает страницу с интернета, уже анализируя полученные данные и сохраняя в определенной структуре в файл.В это же время должен работать еще один поток ThrUpdate. Он скачивает всю туже страницу и наблюдает за появлением новых данных,удалением тех которые уже удалены с той страницы в интернете, и изменением каких то данных.( запускаться поток должен через определенное заданное время)
Вариант (В). Программа запущенна не впервые. В листбокс заносятся данные из сохраненных файлов(учитывая что вариант А полностью отработал в предыдущей загрузке, если нет то скачиваются файлы, которые не были скачаны в пером запуске А). Как только данные занесены, а это происходит весьма быстро так как файлы находяятся на диске в формате txt, то запускается поток ThrUpdate, выполняет те же операции что и в варианте А. Идеально было, если б таких ThrUpdate было больше одного(т.е.ThrUpdate1,2,3,4... которые выполняли свои функции с данными, не обязательно изменявшие данные в листбоксе).
Изучал работу критических секций,мьютексов, семафоров и других вариантов синхронизации. Но понять пока еще трудно. Надеюсь на помощь в создании алгоритмов. Надеюсь услышать советы: что лучше использовать в моем случае, на что обратить внимание.
P.S. Программа будет работать с моим сайтом. Для скачивания содержимого страниц используется idhttp.
Заранее благодарен.
Сергей М. (2009-02-02 12:54:00) [61]
> Тимоха (02.02.09 12:40) [54]
А зачем потоку знать про какие-то формы и окна ?
Достаточно сказать ему, мол, на тебе первым параметром конструктора URL, делай свое дело, когда будешь готов отдать результат работы, вызови вот такой-то метод, который тебе передан, например, вторым параметром конструктора.
Тимоха (2009-02-02 12:51:00) [62]Т.е. вы предлагаете в поток вывести только скачку страницы, а результат скачивание отдавать основному потоку и все функции и процедуры, которые парсят текст должны находится тоже в основном потоке?
Медвежонок Пятачок (2009-02-02 12:46:00) [63]Поток должен тягать урл ресурс и уметь возвращать результат вызываеющему коду и больше ничего не должен делать.
тогда он будет полезен с точки зрения повторного использования кода.
а с текущим подходом потребуется для каждого урл ресурса писать отдельные потоки, в которых дублируется один и то же код реализующий взаимодействие с веб-сервером.
Т.е. никому не нужный мартышкин труд.
Будет десять потоков-близнецов.
Однажды ты решишь перейти с инди на что-то другое или просто на другую версию инди где изменена внутренняя иерархия классов - и привет.
Засучивай рукава и модифицируй код всех десяти классов.
Тимоха (2009-02-02 12:40:00) [64]
> Сергей М.
А если попробовать так, создаем буфер, поток в него сохраняет данные и посылает форме сообщение, а та на сообщения добавляет содержимое буфера в листбокс?
> Медвежонок Пятачок
Не совсем понятно что оставлять в основном потоке, а что выносить в раба.
Можете привести пример?
Медвежонок Пятачок (2009-02-02 12:27:00) [65]TTest = class(TThread)
...
constructor CreateIt(const AURL : string; AList : TString); override;
end;
Только все равно это будет неправильно.
Нельзя просто взять кусок программы и вынести его в поток.
Выносить нужно со смыслом и чтобы польза была.
Этот твой поток сейчас те самые чернила для седьмого класса.
Содержат код, могущий получить любую страницу, но в методе update подразумевается что это вполне конкретная страница.
Номальные люди так код не структурируют.
Сергей М. (2009-02-02 12:21:00) [66]
> Тимоха
Уже ощутимо лучше.
Но:
1. А если запрашиваемый ресурс окажется недоступным ?
2. А если завтра Form1.lst1 превратятся во что-то другое или совсем исчезнут из проекта ?
Медвежонок Пятачок (2009-02-02 12:17:00) [67]двойка за хардкодед урл.
за Form1.lst1.Items.Add(s); в методе потока расстрел через повешение.
Тимоха (2009-02-02 12:15:00) [68]По нажатию на кнопку, создаю поток, говорю ему чтобы сам освободился, ставлю приоритет ниже vcl'кого, запускаю.
В потоке: создаю http, скачиваю страницу, использую syncronize, в котором ищу имена авторов и добавляю их на форму.
Тимоха (2009-02-02 12:12:00) [69]Спасибо всем за ответы, очень ценю вашу помощь!
Решил попробовать по другому.
Код формы:
procedure TForm1.btn1Click(Sender: TObject);
var
potok: TTest;
begin
potok := TTest.Create(true);
potok.FreeOnTerminate := true;
potok.Priority := tpLowest;
potok.Resume;
end;
код потока:
uses
Classes, idhttp, unit1, StrUtils;
type
TTest = class(TThread)
private
http: tidhttp;
page: string;
{ Private declarations }
protected
procedure update;
procedure Execute; override;
end;
implementation
procedure TTest.Execute;
begin
http := TIdHTTP.Create(nil);
http.ProtocolVersion := pv1_1;
page := http.Get(' http://www.delphimaster.ru/cgi-bin/forum.pl?n=18');
Synchronize(update);
http.Free;
end;
procedure TTest.update;
var
i, index, count: Integer;
s:string;
begin
count := 0;
index := PosEx('<nobr> ', page, count);
repeat
count := PosEx('', page, index);
s := Copy(page, index+9, count - index - 9);
Form1.lst1.Items.Add(s);
index := PosEx('<nobr> ', page, count);
until index = 0;
end;
Ругайте :)
Медвежонок Пятачок (2009-02-02 11:51:00) [70]Смело делай Shift+Del на папке проекта. А Архангельского, или откуда там ты копировал примеры - на растопку.
Потом все сначала и уже с применением мозга.
sniknik (2009-02-02 11:43:00) [71]> и работали сразу несколько процедур параллельно.
при твоем подходе они все будут стоять в очереди у главного... т.е. куча усилий и пшик в итоге.
Сергей М. (2009-02-02 11:43:00) [72]
> Забыл убрать
Так.
Что еще ты забыл убрать ?
sniknik (2009-02-02 11:40:00) [73]> но при этом никто "правильного" кода не приводит :(
вот тут ты врешь... и там главное не код, главное понять в чем к нему претензии, и самому так не делать. вот нафига тебе тут поток если вся работа идет в основном?
р.с. приведи какую нибудь ссылку с плохими отзывами... посмотрим.
> так будет вернее?
у тебя в моторе ломик застрял, из-за которого он не заводится, а ты машине фары меняешь и спрашиваешь "может так заведется?".
Тимоха (2009-02-02 11:39:00) [74]
> Тогда зачем нужен блок перхвата-обработки этого исключения
> ?
Скопировал с примера. Забыл убрать.
Тимоха (2009-02-02 11:38:00) [75]Чтобы был доступ к VCL, не было тормозов, и работали сразу несколько процедур параллельно.
Сергей М. (2009-02-02 11:37:00) [76]
> Задумывался. В моем случае ничто и никто.
Тогда зачем нужен блок перхвата-обработки этого исключения ?
Медвежонок Пятачок (2009-02-02 11:35:00) [77]procedure TThread_Start_First.Execute;
begin
...
syncronize(get_page);
...
syncronize(updateresults);
end;
Код твоего чудесного вторичного потока на 99% работает в контексте главного потока.
Зачем тебе вообще поток понадобился?
Тимоха (2009-02-02 11:34:00) [78]Задумывался. В моем случае ничто и никто.
Сергей М. (2009-02-02 11:32:00) [79]
> Тимоха (02.02.09 11:31) [37]
Еще раз прочитай вопрос в [27] !
Тимоха (2009-02-02 11:31:00) [80]
> Сергей М
Приложение делает попытку ошибочного преобразования целых чисел, чисел с плавающей запятой, дат или времени в строку или ошибочного преобразования строк в эти типы