Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Поток с доступом к глобальной переменной основной программы

Delphi , Компоненты и Классы , Потоки



Автор: Xavier Pacheco

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TMainForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

{ NOTE: Change GlobalStr from var to threadvar to see difference }
var
  //threadvar
  GlobalStr: string;

type
  TTLSThread = class(TThread)
  private
    FNewStr: string;
  protected
    procedure Execute; override;
  public
    constructor Create(const ANewStr: string);
  end;

procedure SetShowStr(const S: string);
begin
  if S = '' then
    MessageBox(0, PChar(GlobalStr), 'The string is...', MB_OK)
  else
    GlobalStr := S;
end;

constructor TTLSThread.Create(const ANewStr: string);
begin
  FNewStr := ANewStr;
  inherited Create(False);
end;

procedure TTLSThread.Execute;
begin
  FreeOnTerminate := True;
  SetShowStr(FNewStr);
  SetShowStr('');
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  SetShowStr('Hello world');
  SetShowStr('');
  TTLSThread.Create('Dilbert');
  Sleep(100);
  SetShowStr('');
end;

end.

Программа на Delphi, демонстрирующая использование глобальной переменной в многопоточной среде.

Программа состоит из двух основных компонентов: формы с кнопкой и класса потока TTLSThread.

Когда кнопка на форме кликается, она вызывает процедуру SetShowStr с строкой "Hello world". Это устанавливает значение глобальной переменной GlobalStr. Затем она создает экземпляр класса TTLSThread с параметром строкой "Dilbert".

Поток выполняется в отдельном потоке и сначала устанавливает глобальную переменную в строку "Dilbert", а затем возвращает ее в пустую строку. Затем программа спит на 100 миллисекунд перед тем, как установить глобальную переменную в пустую строку снова.

Вот некоторые вещи, которые стоит отметить:

  1. Глобальная переменная GlobalStr объявлена как обычная переменная, а не как локальная переменная потока (threadvar). Это означает, что все потоки будут доступаться и модифицировать ту же глобальную переменную.
  2. Программа использует функцию Sleep для приостановки выполнения основного потока на 100 миллисекунд. Это используется для демонстрации эффекта, когда поток модифицирует глобальную переменную.

Чтобы увидеть разницу между использованием обычной переменной и локальной переменной потока, можно uncomment строку //threadvar перед объявлением GlobalStr. Это объявит GlobalStr как локальную переменную потока, что означает, что каждый поток будет иметь свой отдельный экземпляр переменной. В этом случае основной поток не увидит изменения, сделанные потоком.

В целом, программа демонстрирует использование глобальных переменных в многопоточной среде и создание и управление потоками в Delphi.

Вот некоторые предложения по улучшению:

  1. вместо использования Sleep для приостановки выполнения основного потока можно использовать синхронизационные примитивы, такие как семафоры или события, для координации между потоками.
  2. можно добавить более надежное обслуживание ошибок и журналирование, чтобы обеспечить корректное поведение программы в случае ошибок или исключений.
  3. можно рассмотреть использование более сложной модели потока, такой как пул рабочих потоков, для управления множеством задач.concurrently.

Вот обновленная версия кода с некоторыми улучшениями:

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
  TMainForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

{ NOTE: Change GlobalStr from var to threadvar to see difference }
var
  //threadvar
  GlobalStr: string;

type
  TTLSThread = class(TThread)
  private
    FNewStr: string;
  protected
    procedure Execute; override;
  public
    constructor Create(const ANewStr: string);
  end;

procedure SetShowStr(const S: string);
begin
  if S = '' then
    MessageBox(0, PChar(GlobalStr), 'The string is...', MB_OK)
  else
    GlobalStr := S;
end;

constructor TTLSThread.Create(const ANewStr: string);
begin
  FNewStr := ANewStr;
  inherited Create(False);
end;

procedure TTLSThread.Execute;
begin
  FreeOnTerminate := True;
  SetShowStr(FNewStr);
  SetShowStr('');
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  SetShowStr('Hello world');
  SetShowStr('');
  TTLSThread.Create('Dilbert');
  SyncProc; // Wait for the thread to finish
  SetShowStr('');
end;

end.

Я добавил вызов SyncProc после создания потока, который обеспечивает, что основной поток ждет, пока поток не закончит выполнение, прежде чем продолжать. Это предотвращает программу от попытки доступа к глобальной переменной, когда она модифицируется другим потоком.

В статье описывается пример использования потока с доступом к глобальной переменной основной программы в языке Delphi, где создается отдельный поток для выполнения задачи и изменяет значение глобальной переменной.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Потоки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-01-29 03:09:55/0.0037620067596436/0