Потоки в консольном приложении

Вопросы использования сторонних (не входящих в состав FPC и Lazarus) утилит и библиотек.

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

Ответить
Аватара пользователя
Gorjatschew
новенький
Сообщения: 23
Зарегистрирован: 15.01.2008 17:57:06
Откуда: Санкт-Петербург

Потоки в консольном приложении

Сообщение Gorjatschew »

Здравствуйте!
У меня к вам такой вопрос: пишу программу, которая должна пищать системным динамиком и одновременно проигрывать музыкальный файл.
Проблема в том, что попытавшись добиться одновременности, использовал потоки, но, наверное, я чего-то в них недопонимаю.
Программа писалась на делфях.
Вот код:
beep.dpr

Код: Выделить всё

uses
  Thread in 'Thread.pas',
  Windows, SysUtils, Classes, mmsystem;

var
  frequency, duration, count, delay: Integer;
  I: Integer;

procedure Play;
var
  so: TSyncObj;
begin
  so:=TSyncObj.Create(true);
  so.Resume;
  so.Priority:=tpNormal;
//  so.Terminate;
end;

begin
//Если есть флаги частоты и длительности
  if (FindCmdLineSwitch('f', ['-'], true) and FindCmdLineSwitch('d', ['-'], true)) then
    begin
      frequency:=StrToIntDef(ParamStr(2), 2400);
      duration:=StrToIntDef(ParamStr(4), 2500);
//если есть флаги числа повторений и задержки
      if (FindCmdLineSwitch('c', ['-'], true) and FindCmdLineSwitch('s', ['-'], true)) then
        begin
          count:=StrToIntDef(ParamStr(6), 1);
          delay:=StrToIntDef(ParamStr(8), 0);
            for I:=0 to count-1 do
              begin
                Windows.Beep(frequency, duration);
                Play;
                sleep(delay)
              end;
        end
      else
        begin
          Windows.Beep(frequency, duration);
          Play;
        end;
    end
  else
    begin
      if FindCmdLineSwitch('o', ['-'], true) then
        begin
          Play;
        end
      else
        if FindCmdLineSwitch('h', ['-'], true) then
          begin
            MessageBox(0, 'Beep ver. 0.1.5', 'About', MB_ICONINFORMATION);
          end
        else
          Windows.Beep(2400, 2500);
    end;
end.

Thread.pas

Код: Выделить всё

unit Thread;

interface

uses
  Classes;

type
  TSyncObj = class(TThread)
  private
    { Private declarations }
    procedure Play;
  protected
    procedure Execute; override;
  end;

implementation

uses
  Play;

{ Important: Methods and properties of objects in VCL can only be used in a
  method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure TSyncObj.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ TSyncObj }

procedure TSyncObj.Execute;
begin
  { Place thread code here }
  Synchronize(Play);
  if Terminated then exit;
end;

procedure TSyncObj.Play;
begin
  PlayAlarm;
end;

end.

и Play.pas

Код: Выделить всё

unit Play;

interface

uses
  SysUtils, mmsystem;

procedure PlayAlarm;

implementation

procedure PlayAlarm;
begin
//если есть флаг на проигрывание файла
  if FindCmdLineSwitch('o', ['-'], true) then
    begin
//если при этом есть флаги на пищалку
      if (FindCmdLineSwitch('-f', ['-'], true) and FindCmdLineSwitch('-d', ['-'], true)) then
        begin
//и на распределение длительности
          if (FindCmdLineSwitch('-c', ['-'], true) and FindCmdLineSwitch('-s', ['-'], true)) then
            PlaySound(PChar(ParamStr(10)),0,SND_FILENAME)
          else
//просто пищалка
            PlaySound(PChar(ParamStr(6)),0,SND_FILENAME)
        end
      else
//просто проиграть файл
        PlaySound(PChar(ParamStr(2)),0,SND_FILENAME)
    end;
end;

end.


Заранее спасибо!
И если кто предложит альтернативный, причём кроссплатформенный метод, буду благодарен.
З.Ы.
Писал на fpc, запускалось, но на время исполнения на экране появлялось окно командной строки, что не есть гут.
Аватара пользователя
Deepthroat
постоялец
Сообщения: 144
Зарегистрирован: 06.09.2007 00:21:34
Откуда: Outer Heaven
Контактная информация:

Сообщение Deepthroat »

Так а что конкретно не получается? Консольное окно? Ну так {$APPTYPE CONSOLE}. Или что-то еще не так?
Последний раз редактировалось Deepthroat 30.08.2008 00:37:02, всего редактировалось 1 раз.
Аватара пользователя
Gorjatschew
новенький
Сообщения: 23
Зарегистрирован: 15.01.2008 17:57:06
Откуда: Санкт-Петербург

Сообщение Gorjatschew »

Deepthroat писал(а):Так а что конкретно не получается? Консольное окно? Ну так {$APPTYPE GUI}. Или что-то еще не так?

Просто не пашет поток :)
Когда в отладке запускаю, вижу, как он проходит по потоку, но воспроизведения звука почему-то нет.
PublicJoke
новенький
Сообщения: 41
Зарегистрирован: 04.07.2006 12:21:07

Сообщение PublicJoke »

1) Почитайте, для чего нужен и, главное, как работает Synchronize. Причем тут консольное приложение? Вызывайте PlayAlarm непосредственно из Execute
2) Play надо вызывать перед Beep, поскольку Beep - синхронный. Либо оформить его вызов из еще одного потока
3) Не увидел в beep.dpr строки {$APPTYPE CONSOLE}
4) После внесения вышеуказанных изменений у меня все работает (только с ключами Вы, на мой взгляд, намудрили)
5) Если не хотите следить за жизнью потока, рекомендую поставить у него FreeOnTerminate в True
Ответить