Сабж столкнулся с проблемкой и без помощи тут не обойтись. Пишу брут, ЯП delphi. Вообщем приведу сразу код: Это процедура нажатия кнопки старт в основном потоке программы: Code: procedure TMainForm.bStartClick(Sender: TObject); var xid: longword; begin Acc:=TStringList.Create; // для списка акков Pass:=TStringList.Create; // для списка пассов // Дальше цикл перебора для каждого Acc - все Pass for i:=Acc.Count-1 downto 0 do begin // i - глобальная integer for j:=0 to Pass.count-1 do begin // j - глобальная integer // tid:array [0..999] of integer; глобальный массив, счетчик потоков tid[j]:=beginthread(nil,0,Addr(ThreadFunc),nil,0,Xid); //запускаем потоки end; // тут проверка на успешность выполнения всех потоков end; // тут вывожу результаты end; А это процедура нового потока: Code: procedure ThreadFunc; var i_loсal, j_loсal: integer; // локальные i и j results: WideString; // для результата пост запроса Post: TStringList; // для пост запроса x_http: TIdHTTP; err: boolean; // для проверки успешности пост запроса begin try // сохраняем глобальные переменные в локальные, чтобы потоки не конфликтовали i_lokal:=i; j_lokal:=j; Post:=TStringList.Create; [COLOR=Green] // ВОТ ЗДЕСЬ ПРОБЛЕМКА!!! MainForm.lcurrent.Caption:='Acc: '+Acc[i_lokal]+' Pass: '+Pass[j_lokal]; // вот этот label появляется в верхнем левом углу экрана[/COLOR] x_http:=TIdHTTP.Create(nil); // тут создаю динамически IdHTTP x_http.AllowCookies:=true; //Дальше определяю пост запрос try results:=x_http.Post('xxx',Post); // сам пост запрос except err:=true; end; Post.Clear; if(Length(results)>300) then begin // тут валид не валид условие // парсю нужные мне данные good:=good+1; // глобальная переменная для валид [COLOR=Green] // ВОТ ЗДЕСЬ ПРОБЛЕМКА!!! MainForm.lGood.Caption:='Good: '+IntTostr(good);// тоже самое[/COLOR] end else begin bad:=bad+1; // глобальная переменная для не валид [COLOR=Green] // И ВОТ ЗДЕСЬ ПРОБЛЕМКА!!! MainForm.lBad.Caption:='Bad: '+IntTostr(bad); // и здесь тоже появляется этот label в верхнем левом углу экрана.[/COLOR] end; Post.Free; // Освобождаю Post; endthread(0); // закрываю поток end; Вообщем в коде написал коментарии, вот эти лэйблы ложатся друг на друга в верхнем левом углу экрана, причем форма моя находится по центру)) Такое конечно бывает не всегда, где-то 1 раз на 100-200 пост запросов, Если я не заключаю код в потоке в try except, то вылетает ексцепшен " in module 'xxx' at xxxxxxxx "Canvas does not allow drawing". Сам код c try exception работает без проблем, но вот эти лэйблы ужасно раздражают. Может быть кто-нибудь с талкивался с такой проблемкой?
Доступ к визуальным компонентам только из main thread. Запомни это раз и навсегда. Версия дельфи? Нахера beginthread? Да, почти каждый день сталкиваюсь с проблемой отсуствия у новичков базовых знаний
Т.е. из потока мне никак не получится изменить визуальные компоненты формы? 7 А чем плохо? Спасибо за то, что уделил минутку времени, и ответил на мой вопрос, да вообще какие-либо знания о потоках у меня отсутствовали до не давнего времени, теперь пытаюсь наверстать упущенное.
Вот так напрямую - нет. Надо сделать так чтобы операции с компонентами на форме производились только в контексте главного потока. Если бы ты использовал TThread то можно было бы воспользоваться методами Synchronize и Queue для этого. Либо если версия дельфи была бы поновее то статическими методами класса TThread которые можно вызывать в любом месте программы не создавая объекта. А так, даже не знаю, возможно воспользоваться посылкой сообщений SendMesage/PostMessage.. Но TLabel не оконный компонент, сам сообщения обрабатывать не может. Как вариант определить метод в классе формы для обработки сообщения, а в потоке посылать сообщение с помощью SendMessage. Тогда все будет работать нормально. А тем, что смешивание методологий и парадигм. С одной стороны ты юзаешь готовые классы/компоненты а с другой напрямую APi-функции. Вот как результат получаем костыли описанные выше. А вообще, интересно, у тебя что, TLabel новый создается при этом, или старый перемещается?
Code: procedure TMainForm.bStartClick(Sender: TObject); var xid: longword; begin Acc:=TStringList.Create; // для списка акков Pass:=TStringList.Create; // для списка пассов // Дальше цикл перебора для каждого Acc - все Pass for i:=Acc.Count-1 downto 0 do begin // i - глобальная integer for j:=0 to Pass.count-1 do begin // j - глобальная integer // tid:array [0..999] of integer; глобальный массив, счетчик потоков tid[j]:=beginthread(nil,0,Addr(ThreadFunc),nil,0,Xid); //запускаем потоки end; // тут проверка на успешность выполнения всех потоков end; // тут вывожу результаты end; Так никто не делает. Что если у тебя будет 100 паролей и 100 акков? Правильней создать очередь и фиксированное число потоков для ее обслуживания.
++ а еще лучше не фиксированное число потоков а пул потоков на основе порта завершения ввода вывода и глобальную очередь доступ к которой синхронизировать секциями
Спс за ценные советы, учту. Вообще я перенес в основной поток все визуальные преобразования и теперь ничего не появляется и все работает без эксцепшен. Ещё раз Спасибо за базу. Вообще я пробовал использовать Indy компонент для работы с потоками TIdThreadComponent, но ничего хорошего не вышло. Да и на форумах часто видел люди писали, что глючит Indy. Поэтому решил на Апи реализовать, да и не сложно в освоении впринципе. Новый создавался, потому как на самой форме изменения были видны без проблем одновременно с появлением копий этих изменений в верхнем углу экрана. Да я знаю. Такая логика программы только для конкретно моего случая, т.к. максимальное кол-во запросов можно сделать ток 10, потом перерыв в 10 мин, соответственно тут брут идет не для одного юзера, а массовый, рассчитанный на простые пароли. Да конечно это можно обойти используя прокси, но для моей задачи в этом нет необходимости. Спасибо всем, кто помог разобраться так сказать в азах, даже стыдно немножко) Проблема решена. Тему можно закрывать.
QueueUserWorkItem выполняет callback функции в пуле при необходимости увеличивает количество потоков при необходимости уменьшает тоесть весь код обслуживающий пул уже написан можно просто ей воспользоваться останется только написать свой callback и внутри него синхронизировать доступ к очереди хотя да здесь все таки лучше фиксированное число потоков если бы была неизвестна частота запросов и нагрузка то пул был бы лучшим решением