Регистрация Главная Сообщество
Сообщения за день Справка Регистрация

Ответ
 
Опции темы
Старый 21.07.2010, 16:31   #1
Знатный Читер
 Рыцарь
Аватар для TakeThat
 
TakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражанияTakeThat блестящий пример для подражания
Регистрация: 03.08.2009
Сообщений: 391
Популярность: 1541
Сказал(а) спасибо: 225
Поблагодарили 458 раз(а) в 220 сообщениях
Отправить сообщение для TakeThat с помощью Skype™
 
По умолчанию [delphi] Многопоточность

Многопото́чность (Wiki) — свойство платформы (например, операционной системы, JVM и т. д.) или приложения, состоящее в том, что процесс, порождённый в операционной системе, может состоять из нескольких потоков, выполняющихся «параллельно», то есть без предписанного порядка во времени. При выполнении некоторых задач такое разделение может достичь более эффективного использования ресурсов вычислительной машины.

Чаще всего используется при работе с интернетом.

В этом уроке я расскажу как ПРАВИЛЬНО реализовать многоточность в программе. (Кто-то реализует ее иначе, но ИМХО ниже приведенный способ является самым рациональным)

Использовать будем Embarcadero Rad Studio 2010 (2009).

Создадим новый юнит - Thread Object

[Ссылки могут видеть только зарегистрированные пользователи. ]

в имени класса напишем TNewThread
Теперь у нас есть заготовка потока. Сохраним этот файл, как newthread.pas

Вернемся к главной форме. Кинем на форму Memo (переименуем в Code) и Button (Button1).

[Ссылки могут видеть только зарегистрированные пользователи. ]

в uses основной программы добавим наш "потоковый" юнит - newthread
Тыкнем 2 раза на кнопку и в обработчике пропишем одиночный вызов потока:
Код:
procedure TForm1.Button1Click(Sender: TObject);
begin
  TNewThread.create(false);
end;
При создании потока передается логическая переменная. Она отвечает за запуск потока (либо сразу же выполнить код, либо создать поток и ждать команды "выполнить код"). В нашем случае false значит выполнить код сразу после запуска.

Вернемся в поток и добавим после implementation
Код:
uses *имя основного файла*;
а в процедуру Execute следующий код:
Код:
procedure Tnewthread.Execute;
begin
  form1.Code.Text:='Thread Created!';
  self.Terminate;
end;
Запустим программу и нажмем на кнопку. Если тект в поле изменился на Thread Created! значит мы все сделали правильно и можно поздравить себя с успешным запуском потока)

А теперь научимся производить различные действия с потоками, передавать в них дополнительные переменные, вызывать нужно кол-во и контролировать его. А также синхронизировать потоки.

Для начала разберем передачу дополнительных данных в поток. Например прокси или адрес страницы.
Для этого добавим в type потока
Код:
  public
    constructor Create(CreateSuspended: boolean; uid1:string);
CreateSuspended: boolean - та самая переменная, ее необходимо прописать, если будем писать свой "конструктор".

uid1:string - наша дополнительная переменная. Кроме нее добавим в private
uid:string; как глобальную переменную для этого потока и переменную nick:string;

И пропишем саму процедуру (после implementation):
Код:
constructor Tnewthread.Create(CreateSuspended: boolean; uid1: string);
begin
  inherited Create(CreateSuspended);
  Synchronize(inc1);
  uid := uid1;
end;
uid := uid1; - передаем переменную в глобальную. Что такое Synchronize(inc1); я объясню позже.

Теперь усложним наш код потока.
В uses добавим idhttp
А процедура Execute будет выглядеть следующим образом:
Код:
procedure Tnewthread.Execute;
var
  http: tidhttp;
  s: string;
  i: integer;
begin
  try
    nick := '';
    s:='';
    http := tidhttp.Create;
    http.HandleRedirects := true;
    http.request.useragent :=
      'mozilla/3.0 (compatible; msie 7.0; windows nt 5.0)';
    http.request.acceptencoding := 'gzip, deflate';
    http.ReadTimeout := 30000;
    http.ConnectTimeout := 30000;
    try
      s := http.Get('http://exphack.ru/member.php?u='+uid);
    except
    end;
  finally
    try
      if length(s) <> 0 then
      begin
        if pos('Просмотр профиля: ', s) > 0 then
        begin
          for i := pos('Просмотр профиля: ', s) + 18 to length(s) do
            if s[i] = '<' then
              break
            else
              nick := nick + s[i];
          if length(nick) > 0 then
            Synchronize(UpdateGood)
          else
            Synchronize(UpdateBad);
        end
        else
          Synchronize(UpdateBad);
      end
      else
        Synchronize(UpdateError);
    except
    end;
    Synchronize(dec1);
    self.Terminate;
  end;
end;
Начнем разбор.
1 это обнуление глобальной переменной. (В нашем случае обязательно).
2 это, как вы уже догадались парсер форума exphack.ru да и вообще буллетина. Работа с инди думаю понятна, если непонятна - гуглим.

Рассмотрим финал процедуры:
Здесь мы вытаскиваем из полученного кода страницы наш ник. А что же за странные строки с Synchronize?
Это функция вызывающаяся для другой процедуры. Она обеспечивает "очередность" потоков - не дает одновременно нескольким потокам обращатся к переменной. Это важно при использовании таких функций, как inc и dec. Дело в том, что эти функции выполняются в 3 этапа на машинном уровне и если одновременно несколько потоков вызовут их для одной переменной (допустим переменной из основного юнита, отвечающей за кол-во активных потоков) может случится что выскочит лишний +1 или -1.
Соответственно код процедур inc1 и dec1:
Код:
procedure Tnewthread.inc1;
begin
  inc(tpot);
end;

procedure Tnewthread.dec1;
begin
  dec(tpot);
end;
где tpot - глобальная переменная основного юнита, отвечающая за число активных потоков.
Тоесть - при запуске потока она увеличивается на 1, а при завершении уменьшается на 1. Обязательно прописывайте inc1 в конструкторе, а не в Execute!

Ну а процедуры Update отвечают за вывод нужных результатов куда надо (файлы, поля, количественные переменные и т д)
Не забудьте что все эти процедуры необходимо прописать в protected:
Код:
    procedure Updategood;
    procedure UpdateBad;
    procedure UpdateError;
    procedure inc1;
    procedure dec1;
Теперь наш поток полностью готов. Но необходимо еще и контролировать их кол-во.

Для этого я использую следующий метод их вызова и ожидания:
В основном потоке при нажатии кнопки происходит:
Код:
  k:=*начальный уид*;
  maxuid:=*конечный уид*;
  maxthreads:=*кол-во потоков*;
  tpot:=0;
  while k<=maxuid do
    begin
      application.processmessages();
      if tpot = maxthreads then
        while tpot = maxthreads do
        begin
          sleep(10);
          application.processmessages();
        end;
      Tnewthread .Create(false, inttostr(k));
      inc(k);
    end;
Ну и часто надо дождаться пока завершаясь ВСЕ потоки:
Код:
while tpot > 0 do
    begin
      sleep(10);
      application.processmessages();
    end;
Выкладываю код потока: [Ссылки могут видеть только зарегистрированные пользователи. ]

P.S Для корректной работы с интернетом необходимы библиотеки Indy ПОСЛЕДНЕЙ версии!

by Z.Рэйзор and takethat
  Ответить с цитированием
2 пользователя(ей) сказали cпасибо:
demonn1994 (21.07.2010), mr*WOLF (18.02.2013)
Старый 28.07.2010, 12:01   #2
Заблокирован
 Разведчик
Аватар для relex22rus
 
relex22rus на правильном пути
Регистрация: 01.01.2010
Сообщений: 24
Популярность: 56
Сказал(а) спасибо: 22
Поблагодарили 23 раз(а) в 14 сообщениях
 
По умолчанию Re: [delphi] Многопоточность

Indy ПОСЛЕДНЕЙ версиии

где скачать? а то куда не захожу везде платно..
скинь ссыль
  Ответить с цитированием
Старый 31.07.2010, 07:42   #3
Super Moderator
 Сержант
Аватар для Рэйзор
 
Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(Рэйзор сломал счётчик популярности :(
Регистрация: 20.07.2010
Сообщений: 137
Популярность: 26409
Сказал(а) спасибо: 52
Поблагодарили 566 раз(а) в 197 сообщениях
 
По умолчанию Re: [delphi] Многопоточность

Цитата:
Сообщение от relex22rusПосмотреть сообщение
Indy ПОСЛЕДНЕЙ версиии

где скачать? а то куда не захожу везде платно..
скинь ссыль

с офф репозиториев
че и как делать подробно описано тут:
Код:
http://kvendi.pp.ru/?p=66
http://kvendi.pp.ru/?p=89
  Ответить с цитированием
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Точность kAwAii Вопросы и ответы, обсуждения 1 20.12.2012 22:45
Безконечность Robix PVP Room 13 17.08.2010 19:40
[Баг] Баг на Точность (Accurancy) Hummel Rising Force Online 1 28.03.2009 13:38

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 15:32.

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net