1
  1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
Приветствуем вас,Гость, на форуме IFUD.WS. Обязательно рекомендуется к прочтению правила форума http://ifud.ws/threads/obnovleno-pravila-foruma.7759

Реализация многопоточности

Тема в разделе "Программирование", создана пользователем googie, 7 фев 2013.

  1. TopicStarter Overlay
    googie

    googie Команда форума

    Регистрация:
    27 июл 2012
    Сообщения:
    824
    Симпатии:
    616
    Реализация многопоточности в delphi.
    Вижу множество вопросов на разных форумах по программированию которые относятся к многопоточности. В этой статье я бы хотел не только объяснить как реализовать это в delphi, но и предоставить готовый шаблон многопоточного приложения который вы бы могли использовать в дальнейшем в своих программах.

    Для начала немного теории. Одной из важнейших вещей в многопоточном приложении является синхронизация потоков. Если не учесть, синхронизацию потоков, то это, может привести к плачевным последствиям. Давайте рассмотрим такой пример, после чего у вас в голове всё встанет на свои места.
    У нас в программе имеется переменная, назовём её - "int" - типа integer. Если мы будем присваивать ей значение из основного потока, то всё будет хорошо, и проблем не возникнет. Мало того, если даже мы присвоим ей значение из дополнительного потока который мы создали, то всё будет хорошо. Но так как зачастую у многопоточного приложения более одного дополнительного потока, то зададимся вопросом- "А, что будет если мы попытаемся присвоить переменной значение из двух потоков одновременно?". Вот тут, и произойдёт то таинственное события при котором переменной присвоится значение которое скорее всего не будет равно ни одному из значений которых вы планировали ей присвоить. Тогда и вступает в игру метод синхронизации synchronize. С помощь данного нам разработчиками delphi метода, вы можете обеспечить безопасное обращение нескольких потоков к одной переменной. Данный метод обеспечивает следующие: при вызове процедуры с помощью synchronize она начинает выполнятся, а все остальные процедуры вызванные с помощью этого метода встают в очередь и ждут выполнения текущей процедуры. Всё вышеописанное относится только к записи переменных, а читать можно одновременно из нескольких потоков и ничего плохого не произойдёт. Ну а теперь перейдём к практике.

    И так создадим новый проект. И начнём писать поток. После вот этих строк:
    Код:
    Код:
    private
        { Private declarations }
      public
        { Public declarations }
      end;
    Добавим свои:
    Код:
    Код:
    potok = class(TThread) //Этой строкой мы унаследовали класс потока
      private
      str: string;//в разделе private описываются переменные с помощью которых мы
      nomer : Integer;//будем передавать значения между процедурами внутри потока
      protected
        procedure Execute; override;//это главная процедура потока, она начинает свою работу
    //после того как мы создали поток
      public
        procedure synchro;//в разделе public вы можете объявить процедуры какие только душе
    //угодно
        constructor Create(CreateSuspended: Boolean);//эта строка говорит о том, что мы в
    //implementation опишем конструкцию
    //потока
      end;
    Ну здесь вроде бы всё понятно, вы можете добавлять сколько угодно переменных и процедур для удобства работы.

    Под implementation нам надо описать конструкцию потока, в данном примере это не обязательно, но, что бы вы знали на будущие мы всё равно это сделаем.
    Код:
    Код:
    constructor potok.Create(CreateSuspended: Boolean);
    begin
      inherited Create(CreateSuspended);//Эта строка говорит о том, что поток после создания
    //будет приостановлен если ему передать значение true при создание, если false, то сразу
    //начнёт работу.
    end;
    Добавим в глобальные переменные переменную - "nom" - типа integer, а так же массив наших потоков.
    Код:
    Код:
    var
      Form1: TForm1;
      nom:integer;
      a: array [1..10] of potok;//массив для хранения наших потоков
    Теперь нужно описать процедуры потока, под implementation добавляем следующие:
    Код:
    Код:
    procedure potok.Execute;//начинаем описывать главную процедуру потока
    var
    i:integer;
    begin
    for i:=0 to 100 do
    begin
    sleep(1000);
    synchronize(synchro);//этой строкой мы вызываем процедуру synchro в единичном экземпляре
    end;
    end;
     
    procedure potok.synchro; //описываем ещё одну процедуру потока, которая будет менять
    //загаловок form1
    begin
    inc(nom);
    form1.Caption:='Поток делает своё дело - '+inttostr(nom);
    end;
    Собственно всё готово, остаются только запустить потоки. Кидаем кнопку на форму, "кастуем на неё даблклик" и пишем:
    Код:
    Код:
    procedure TForm1.Button1Click(Sender: TObject);
    var
    pot:integer;
    begin
    for pot:=1  to 10 do  //цикл запускает 10 потоков, которые будут изменять заголовок
      a[pot]:=potok.Create(false); //формы, так же идёт
    //добавление в массив, что бы потом вы могли уничтожить
    //один поток.
      end;
    Вот так выглядит программа в итоге:
    Код:
    Код:
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
     
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    potok = class(TThread) //Этой строкой мы унаследовали класс потока
      private
      str: string;//в разделе private описываются переменные с помощью которых мы
      nomer : Integer;//будем передавать значения между процедурами внутри потока
      protected
        procedure Execute; override;//это главная процедура потока, она начинает свою работу
    //после того как мы создали поток
      public
        procedure synchro;//в разделе public вы можете объявить процедуры какие только душе
    //угодно
        constructor Create(CreateSuspended: Boolean);//эта строка говорит о том, что мы в
    //implementation опишем конструкцию
    //потока
      end;
     
    var
    a: array [1..10] of potok;
      Form1: TForm1;
      nom:integer;
    implementation
    constructor potok.Create(CreateSuspended: Boolean);
    begin
      inherited Create(CreateSuspended);//Эта строка говорит о том, что поток после создания
    //будет приостановлен если ему передать значение true при создание, если false, то сразу
    //начнёт работу.
    end;
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
    pot:integer;
    begin
    for pot:=1  to 10 do  //цикл запускает 10 потоков, которые будут изменять заголовок
      a[pot]:=potok.Create(false); //формы, так же идёт добавление в массив, что бы потом вы могли их уничтожить по одному.
      end;
     
    procedure potok.Execute;//начинаем описывать главную процедуру потока
    var
    I:integer;
    begin
    for i:=0 to 100 do
    begin
    sleep(1000);
    synchronize(synchro);//этой строкой мы вызываем процедуру synchro в единичном экземпляре
    end;
    end;
     
    procedure potok.synchro; //описываем ещё одну процедуру потока, которая будет менять
    //загаловок form1
    begin
    inc(nom);
    form1.Caption:='Поток делает своё дело - '+inttostr(nom);
    end;
     
     
    end.
    Запускаем программу, и нажимаем на кнопку. И видим как в заголовке формы по очереди увеличивается число. ЧТД как говорится. Удачи в создание приложений.

    С уважением Tip.the.besT.
    (c) брутзона.ру
     
    • Like Like x 4
    Метки:
  2. Walentinka

    Walentinka

    Регистрация:
    29 янв 2013
    Сообщения:
    96
    Симпатии:
    47
    Полезная статья, для форума.
    Главное обьяснить на понятных примерах, а когда понимаешь сам принцип уже можно переходить и к более сложному применению.
     
  3. ErrorNick

    ErrorNick

    Регистрация:
    6 июл 2012
    Сообщения:
    126
    Симпатии:
    55
    Хоть статью писал и

    **Скрытый текст: Для просмотра скрытого текста Вы должны авторизоваться.**

    Пожалуйста Зарегистрируйтесь или Войдите для того чтоб увидеть текст сообщения!

    но действительно его реализация дала в массы нормальных брутов.
     
  4. TopicStarter Overlay
    googie

    googie Команда форума

    Регистрация:
    27 июл 2012
    Сообщения:
    824
    Симпатии:
    616
    нормальные исходники в паблик почти не сливают, так что привыкай
     
  5. LulzGhost

    LulzGhost

    Регистрация:
    26 июл 2012
    Сообщения:
    50
    Симпатии:
    17
    полезно для меня
     

Поделиться этой страницей

Загрузка...