Доброго времени суток тру кодеры! объясните чайнику как грамотно организовать взаимодействие/работу билдеровских потоков (TThread) с визуальными элементами/компонентами формы. пробывал юзать Synchronise. с этим методом прога дохнет быстрей чем при прямом обращении к компоненту. тестил вчера на спамере стен. думал как выводить кол-во отправленых сообщений... пришла в голову тупая мысль: кинуть на форму таймер и выводить значение переменной в лейбл... но как тогда вобще грамотно выводить сообщения скажем в MemoLog? (в головву только приходит опять же тупая мысль: сохранять в файл и оттуда читать) в общем я в тупике. выручайте. заранее благодарю. надеюсь более менее понятно изложил суть проблемы.
Лично у меня это реализовано с помощью трех объектов: таймер, лейбл и переменная. В синхронизации поток передает результат в эту переменную, а таймер через заданный промежуток времени выводит в лейбл значение этой переменной. Вот и все. Пример: Code: unit MyThread; ... procedure TMyThread.Sync; begin Inc(Param); end; ... unit Main; ... //Глобальные переменные var Form1: TForm1; Param:integer; ... procedure TForm1.Timer1Timer(Sender: TObject); begin Label1.Caption:='Готово: '+IntToStr(Param); end; ... Для MemoLog'а также можно использовать переменную. Типа TStringList, например.
brutos твой подход ошибочен, т.к. сама модификация Param происходит в потоке. в случае с целыми достаточно InterLockedIncrement а вот с TStringList так делов наворотишь, потом будешь плеваться откуда баги на ровном якобы месте. good_man способов с визуальными элементами только два - Syncronize и Queue. Если у тебя что-то не так - значит не так сделано. Аа, вру, еще есть с отправкой сообщений венды, но это для тебя сложновато и объяснять долго.
ах да, еще чуть не забыл, очень меня мучает такой вопрос: многопоточность. запутался. создаю потоки: for(int i=0; i<thr_count; i++) { Wall_Sender*thr[100]; thr=new Wall_Sender(true); thr->Resume(); } то есть все они создаются почти моментально. нужно взять из мемо аки: String acc= Form1->MemoAccs->Lines->Strings[accs]; //accs-глобальная int String login=acc.SubString(1,acc.Pos(":")-1); String pass=acc.Delete(1,acc.Pos(":")); Form1->MemoLog->Lines->Add(pass+":"+login); как сделать? вот это для меня настоящий тупик. то есть если воткнуть accs++ даже после String acc= Form1->MemoAccs->Lines->Strings[accs]; , выбрать много потоков то они будут брать один и тот же ак. А теперь еще вопрос: можно ли так вобще делать? читать и обращаться напрямую к мемо из потока ? upd: GhostOnline вчера всю ночь сидел изучал работу проги. почти после каждой операции логировал. код у меня минимален и в нем я как бы разбираюсь. прога висла все время перед кодом где идет обращение к визуальному компоненту.
нет, нет, и еще раз нет Почему бы не завести поле в классе потока и не передавать акк ему в конструктор? Видимо плохо понимаешь. Длительные операции внутри Synchronize обычно к такому приводят.
можно поподробнее? что за поле? и как ему передавать?) я не совсем прогер. просто любитель. кодю нетак давно.
Поподробнее то можно, но целесообразно ли. Объясню это - появятся другие вопросы, и так далее, рекурсия Раз уж ты любитель, то время у тебя есть и торопиться некуда - почитай про классы.
GhostOnline ну хотя бы вкратце. у меня в личке столько литературы ппц (скинул один добрый человек) просто читать долго+задолбаешься искать именно по этой теме. а у меня спамер полудохлый так и просит доделать его. мне аж кошмары снятся. как доделаю буду читать книги
Критические секции. Как то так (Delphi) PHP: CriticalS.Enter; Inc(ThreadCount); t_num := ThreadCount; MainForm.LogText.Lines.Add('Поток #'+IntToStr(t_num)+' создан.'); CriticalS.Leave;
ребят а можно делать так: void __fastcall WallSend::ImageLoad() { Form1->Image1->Picture->LoadFromFile(wall_cap_sid+".jpg"); } void __fastcall WallSend::UpdateMemoLog() { Form1->MemoLog->Lines->Add("отправлено на стену "+friends->Strings[fr_id]); } void __fastcall WallSend::UpdateLabel3() { Form1->Label3->Caption=mess_count; } ? и как быть с вопросом #4?
Фэйл. Для кого авторы постоянно подчеркивают что с формой может работать только main thread? Критические секции надо использовать при общем доступе к данным, а не визуальным элементам. А Synchronize как раз гарантирует что метод будет выполнен в контексте главного потока. С++ вообще не знаю, но попытаюсь изобразить В классе потока добавляешь поле, что-то навроде: PHP: class Wall_Sender : TThread{ ......................... private String Account; ........................ } Переопределяешь конструктор класса потока, мм..мб так как-то: PHP: Wall_Sender(String Acc) { ........... Account = Acc; ........... Resume; } То бишь Account это строка вида login;pass А создаешь уже так: PHP: thr[i]=new Wall_Sender(Form1->Memo1->Lines[i]);