По задумке гружу лист в программу с видом ссылок: Code: кошка:матрёшка черепашка:ниндзя и она выдирает из них окончания после знака : ну и выдирать то она выдирает да только потоки неадекватно себя ведут то потоки берут по две одинаковых строки, то не с начала работают и в конце 4-5 одну и ту же строку берут ! PHP: unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Graphics, Forms, syncobjs, Dialogs, StdCtrls, Controls, Classes;type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; Button3: TButton; OpenDialog1: TOpenDialog; Edit1: TEdit; Label1: TLabel; Label2: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); end; th = class(TThread) private // public procedure sync; protected constructor create(createsuspended:boolean); procedure Execute; Override;end;var Form1: TForm1; work: boolean; log:integer; logins: tstringlist; cs: tcriticalsection; res:string;implementation{$R *.dfm}constructor th.create(createsuspended:boolean);begininherited Create(CreateSuspended);freeonterminate:=trueend;procedure TForm1.Button1Click(Sender: TObject);beginif opendialog1.Execute thenbegin logins:=tstringlist.Create; logins.Clear; logins.LoadFromFile(opendialog1.FileName); label2.Caption:=inttostr(logins.count-1);end;end;procedure TForm1.Button2Click(Sender: TObject);varthreads:integer;beginif logins.count<>0 then Work:=True; log:=-1; for threads:=1 to 10 do begin th.Create(false);end;end;procedure th.Execute;beginwhile work do begincs.Enter;inc(log);cs.Leave;if work thenSynchronize(sync);end;end;procedure TForm1.Button3Click(Sender: TObject);beginwork:=false;end;procedure th.sync;beginif log=logins.Count-1 then work:=false;form1.Memo1.Lines.Add(copy(logins[log],pos(':',logins[log])+1,length(logins[log])));form1.Label1.Caption:=inttostr(form1.Memo1.Lines.count-1);end;initializationcs:=TCriticalSection.Create;work:=false;finalizationcs.Free;end. А с одним потоком for threads:=1 to 1 do th.Create(false); всё работает как часы ! В чём вызвана данная проблема ?
log у тебя будет рандомным. И будет это все не по порядку а типо 1,5,2,4,3. Этот самый log надо скопировать в локальную переменную потока а не юзать глобально. Ну или передавать в качестве параметра. А чтобы узнать когда треды завершатся - можно уменьшать переменную с количеством общей работы. Но вообще все это делается немного по другому... Кодес у тебя суровый очень хоть и небольшой. Практически согласуется с древними индусскими манускриптами
Люблю простоту в своих программах =) ещё есть поговорка такая простота - надёжность ! Я теперь то понял разницу когда log глобальная она передаётся как бы из формы, а не из потока и я заставляю как бы потоки работать с формным log ) но не понимаю как всё поправить точнее как бы понимаю, но лучше бы простым способом без Dec(Threads);
Есть такое понятие как конкурентные запросы, когда потоки пытаются получить доступ к одному и тому же источнику данных в один и тот же момент времени. Данные в твоем случае должны быть либо блокированы для других потоков - когда какой либо поток с ними работает, то есть если какой либо поток получил доступ к данным, то данные должны быть заблокированы и недоступны для других потоков, другие потоки ожидают когда данные освободятся. Когда поток получил то что хотел, то он освобождает данные, и они становятся доступны для других потоков, но такой алгоритм не очень эфективный если данных много. Лучше заранее нужно разделить данные на равные части и предоставить каждому потоку лишь свой разделенный участок. Почитай про мьютексы и про симофоры.
Ах вот зачем это условие было нужно, а я его откинул спасибо тебе огромное))) if tread<logins.Count then log:=tread else Work:=False; и всё работает ) tread - глобальная переменная log - в раздел public
Не понял что ты сделал но рад что получилось : ))) В следующий раз юзай параметры. Тоесть отделяй тред от глобальных переменных полностью. "Простота" иногда совсем не простота. Если бы я писал так как ты - я бы уже давно полысел и отнюдь не от простоты. Логика она и в Африке логика. Так что если написать с точки зрения гениев "некрасиво" - то все-же можно написать правильно. И никто не виноват что "вы, смертные, меня не понимаете". Эта простота в могилу тебя заведет И именно для этого делаются якобы "усложнения". Бывают усложнения технические, когда ты треды будишь через APC. Это уже наверное да, подход системщика. Оно круче получается но сложнее. А есть именно "усложнения" которые в реале - упрощения. Если тебе надо перебрать список - то берешь обычный среднестатистический цикл и каждому треду даешь из него свое "задание". Тоесть в твоем случае передаешь пару логин:пароль. И тред работает непосредственно со своим заданием и не лезет туда, куда его не просят. (это первый уровень скажем так). Выполнил задание - возвращаешь результат, юзая мьютекс. Все просто как дверь и надежно. И без багов. И еще проще чем "по простому". ================= Да и... надо наверное предусмотреть: это не будет работать медленнее чем если каждый тред будет брать задание сам. Это будет работать быстрее. (просто однажды я так ошибался... решил что нелишне сказать)