Консольное приложение и потоки

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Консольное приложение и потоки

Сообщение son » 05.10.2015 15:35:54

Здравствуйте. Столкнулся с проблемой. Сделал консольное приложение. У него есть поток, который должен отправлять в консоль сообщения. Так вод в методе Execute вывод данных подвисает. Вот код приложения:
Код: Выделить всё

program thtest;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils, CustApp, ther
  { you can add units after this };

type

  { Tthtest }

  Tthtest = class(TCustomApplication)
  protected
    FHER : TTher;
    procedure DoRun; override;
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
    procedure WriteHelp; virtual;
  end;

{ Tthtest }

procedure Tthtest.DoRun;
var
  ErrorMsg: String;
  i : integer;
begin
  // quick check parameters
  ErrorMsg:=CheckOptions('h','help');
  if ErrorMsg<>'' then begin
    ShowException(Exception.Create(ErrorMsg));
    Terminate;
    Exit;
  end;

  // parse parameters
  if HasOption('h','help') then begin
    WriteHelp;
    Terminate;
    Exit;
  end;
  FHER.Resume;
  i:=0;
  while i<10 do begin
    inc(i);
    Sleep(1000);
  { add your program here }
  end;

  ReadLn;
  // stop program loop
  Terminate;
end;

constructor Tthtest.Create(TheOwner: TComponent);
begin
  FHER := TTher.Create(true);

  inherited Create(TheOwner);
end;

destructor Tthtest.Destroy;
begin
  FHER.Destroy;
  inherited Destroy;
end;

procedure Tthtest.WriteHelp;
begin
  { add your help code here }
  writeln('Usage: ',ExeName,' -h');
end;

var
  Application: Tthtest;
begin
  Application:=Tthtest.Create(nil);
  Application.Title:='thtest';
  Application.Run;
  Application.Free;
end.


Поток тоже простой:
Код: Выделить всё

unit ther;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;
type

  { TTher }

  TTher = class(TThread)
    private
      FMess : string;
      procedure SendMessLog(strMess : string);
      procedure SynchSendMessLog;
    protected
      procedure Execute;override;
    public
      constructor Create(CreateSuspended: Boolean);
      destructor Destroy;override;
  end;

implementation

{ TTher }

procedure TTher.SendMessLog(strMess: string);
begin
  FMess:=strMess;
  Synchronize(@SynchSendMessLog);
end;

procedure TTher.SynchSendMessLog;
begin
  writeln(FMess);
end;

procedure TTher.Execute;
begin
  SendMessLog('EXECUTE');
  sleep(100);
end;

constructor TTher.Create(CreateSuspended: Boolean);
begin
  SendMessLog('CREATE');
  inherited Create(CreateSuspended);
end;

destructor TTher.Destroy;
begin
  SendMessLog('DESTROY');
  inherited Destroy;
end;
end.


Такое ощущение, что при вызове SendMessLog в методе Execute он зависает в ожидании. Чувствую что истина где то рядом, но понять не могу. После разрушения потока в консоль выводится два раза DESTROY.
son
новенький
 
Сообщения: 39
Зарегистрирован: 22.11.2011 11:50:58

Re: Консольное приложение и потоки

Сообщение wavebvg » 05.10.2015 16:25:13

Когда Вы вызываете
Код: Выделить всё
Synchronize(@SynchSendMessLog);
предполагается, что необходимо синхронизировать поток исполнения с циклом обработки сообщений основного потока приложения.

У Вас этого цикла нет, поэтому работать не будет.
В случае вывода в консоль - никакой синхронизации не нужно, вообще, синхронизация, чаще всего, нужна именно для того, чтобы что-то выполнить с GUI. В остальных случаях необходимо лишь недопустить параллельного изменения данных из конкурирующих потоков.
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Консольное приложение и потоки

Сообщение son » 05.10.2015 16:39:31

Ок. То есть непосредственный вызов WriteLn из потока не приведет к краху или ошибкам? Спасибо за ответ!
son
новенький
 
Сообщения: 39
Зарегистрирован: 22.11.2011 11:50:58


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 243

Рейтинг@Mail.ru