Вот написал простенький сортировщик почты на одном потоке.Как его реализовать в многопоточное приложения? Например: Чтоб можно было выбрать количество потоков... 1 поток выбирает 1 строку и сортирует 2 поток выбирает 2 строку и сортирует и так далее... Вот сама программа + исходный код ТУТ И еще вопрос: Terminate; в моем коде не работает, может надо создавать поток с другими параметрами? Code: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Unit2, XPMan; type TForm1 = class(TForm) Memo1: TMemo; Memo2: TMemo; Memo3: TMemo; Memo4: TMemo; Label1: TLabel; Label2: TLabel; Label3: TLabel; Button1: TButton; XPManifest1: TXPManifest; Button2: TButton; Button3: TButton; Button4: TButton; procedure Button1Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; new:TNew; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin new:=TNew.Create(True); new.FreeOnTerminate:=true; new.Priority:=tpNormal; new.Resume; end; procedure TForm1.Button4Click(Sender: TObject); begin new.Terminate; end; procedure TForm1.Button2Click(Sender: TObject); begin new.Suspend; end; procedure TForm1.Button3Click(Sender: TObject); begin new.Resume; end; end. Code: unit Unit2; interface uses Classes; type TNew = class(TThread) private { Private declarations } protected procedure Execute; override; end; implementation uses Windows, Messages, SysUtils, Variants, Graphics, Controls, Forms, Dialogs, Unit1; procedure TNew.Execute; var i:integer; s:string; begin for i:=0 to Form1.Memo1.Lines.Count-1 do begin if pos('mail.ru',Form1.Memo1.Lines[i])<>0 then begin s:=copy(Form1.Memo1.Lines[i],1,length(Form1.Memo1.Lines[i])); Form1.Memo2.Lines.Add(s); end; if pos('rambler.ru',Form1.Memo1.Lines[i])<>0 then begin s:=copy(Form1.Memo1.Lines[i],1,length(Form1.Memo1.Lines[i])); Form1.Memo3.Lines.Add(s); end; if pos('yandex.ru',Form1.Memo1.Lines[i])<>0 then begin s:=copy(Form1.Memo1.Lines[i],1,length(Form1.Memo1.Lines[i])); Form1.Memo4.Lines.Add(s); end; end; end; end.
1) Зачем это делать многопоточным? 2) Terminate не завершает поток, а меняет значение переменной Terminated на true;
На примере этой программы хочу узнать как создать многопоточное приложение. При работы с большим количеством почты многопоточность уменьшит затраченное время на сортировку. Прочитал в таблице что " Terminate - Метод Вызывается для завершения потока." Если это не так то тогда как полностью завершить поток?
Делаешь в потоке цикл while (Terminated = false) do и все. И поток будет работать пока terminated не вернет true
1 поток выбирает 1 строку и сортирует 2 поток выбирает 2 строку и сортирует заюзай такой алгоритм пусть строки будут глобальным массивом и количество потоков тоже глобальной переменной (глобальной - видной всем потокам) через переменную ты передаешь функции потока стартовый номер строки с которой считать а в потоке циклом i=start; while (Terminated != false) { ... i=i+count_thread; if(i>count_array) i=start; } что-то типа...
Code: unit Unit2; interface uses Classes, SysUtils; type TMailHost = (mhNone, mhMail, mhRambler, mhYandex); TNew = class(TThread) private { Private declarations } fMail: string; fMailHost: TMailHost; procedure GetNextMail; procedure SaveResult; protected procedure Execute; override; end; implementation uses Unit1; { TNew } procedure TNew.Execute; begin while not Terminated do begin fMailHost:=mhNone; Synchronize(GetNextMail); if pos('mail.ru', fMail)>0 then fmailHost:=mhMail else if pos('rambler.ru', fMail)>0 then fMailHost:=mhRambler else if pos('yandex.ru', fMail)>0 then fMailHost:=mhYandex; Synchronize(SaveResult); end; end; procedure TNew.GetNextMail; begin fMail:=''; if Form1.Memo1.Lines.Count>0 then begin fMail:=LowerCase(Form1.Memo1.Lines[0]); Form1.Memo1.Lines.Delete(0); end; end; procedure TNew.SaveResult; begin case fMailHost of mhNone: ; mhMail: Form1.Memo2.Lines.Add(fMail); mhRambler: Form1.Memo3.Lines.Add(fMail); mhYandex: Form1.Memo4.Lines.Add(fMail); end; end; end. Это код для потока. Как создать и убить N-ное количество потоков тебе уже рассказали
Согласен. Но в качестве опыта подойдет. Увеличит из-за накладных расходов на синхронизацию. И чем больше будет потоков, тем медленнее будет работать, такой вот парадокс.
дополнение: на однопроцессорных системах увеличит на системах с количеством процессоров > 1 можно добится лучших результатов чем с одним потоком каждый поток на своем процессоре реальное одновременное выполнение а не фиктивное как на одном процессоре
Я прикидывал от нефиг делать - 2 потока на ядро дает прирост примерно 12%, три потока на ядро всего 1%, выше уже в минус
конечно тут же очень важно чем занимаются потоки если например числодробильню разделить на два потока на однопроцессорной машине то только снизиш производительность а если например сетевой ввод вывод на той же однопроцессорной машине то можно весьма неплохо поднять эту самую производительность если прикрутить больше одного потока
Разобрался и все получилось, а теперь вопрос при 2 и более потоках TidHttp надо синхронизировать или поставить в критическую секцию?
Нужно создавать объект TIdHTTP в потоке. Если все хттп-запросы будут в крит.секции, то какой смысл в многопоточности?
Спасибо все помогло, но я заметил что TidHttp только на 30 потоков хватает... Теперь вопрос такой, как сделать паузу/продолжить всех потоков и завершение?
Запускаю 100 потоков(Выполнение простого гет запроса), а в снифере всего 32 отображается... Про Suspend и Resume я уже понял. var i:integer; begin for i:=1 to SpinEdit1.Value do thr.Suspend; end; И также Resume А вот проблемма, как их закончить всех?.
Да ты оказался прав снифер не отображал все запросы(После перезапуска все нормально было) Пробывал закончить все потоки так, но не выходит! Code: procedure tnew.Execute; begin while not Terminated do begin {Мой код} end; end; На кнопку поставил и жму. Code: var thr: array [1..100] of TNew; procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin for i:=1 to SpinEdit1.Value do begin thr[i].Terminate; end; end; Хотя если сделать так то поток не выполняется while (Terminated = true) do begin end; Значить Terminate не чего не возвращает и Terminated не меняется с False на True. Как же их закончить?