Как создать консольное приложение, которое не завершается? - PullRequest
2 голосов
/ 07 апреля 2010

В C ++ консольное приложение может иметь обработчик сообщений в своей процедуре Winmain. Как это:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG msg;

    #ifdef _DEBUG
    CreateConsole("Title");
    #endif

    hwnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
    PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
    while(msg.message != WM_QUIT)
    {
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if(IsDialogMessage(hwnd, &msg))
                continue;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

    }

    return 0;
}

Это делает процесс не закрытым, пока окно консоли не получит сообщение WM_QUIT.Я не знаю, как сделать что-то подобное в Delphi.

Мне нужен не точно обработчик сообщений, а легкая «хитрость», чтобы заставить консольное приложение работать как приложение с графическим интерфейсом с использованием потоков.Так, например, два сервера Indy TCP могут обрабатываться без остановки консольного приложения.

Мой вопрос: как это можно сделать?

Ответы [ 4 ]

8 голосов
/ 07 апреля 2010

Я не уверен, что понимаю, что вам нужно сделать, но, может быть, что-то вроде этого

program Project1;

{$APPTYPE CONSOLE}

uses
  Forms,
  Unit1 in 'Unit1.pas' {DataModule1: TDataModule};

begin
  Application.Initialize;
  Application.CreateForm(TDataModule1, DataModule1);
  while not Application.Terminated do
    Application.ProcessMessages;
end.

с чего начать? Это консольное приложение, которое будет закрываться при закрытии консоли. Вы можете использовать компоненты Indy в модуле данных.

Edit:

Альтернатива без единицы Forms:

program Project1;

{$APPTYPE CONSOLE}

uses
  Windows;

var
  Msg: TMsg;
begin
  while integer(GetMessage(Msg, 0, 0, 0)) <> 0 do begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end.

Я думаю, однако, что это не будет работать с большинством компонентов Delphi - я не знаю об Indy, но если один из его модулей в любом случае приносит модуль Forms, то первая версия предпочтительнее IMO.

1 голос
/ 07 апреля 2010

Все, что вам нужно для программы, которая никогда не завершается, - это бесконечный (или неопределенный) цикл. Ваша программа на C ++ содержит неопределенный цикл: блок while(msg.message != WM_QUIT). TApplication Delphi содержит очень похожий неопределенный цикл. Если вы используете консольное приложение вместо TApplication, все, что вам нужно сделать, это написать собственный неопределенный цикл и поместить его в процедуру в нижней части стека вызовов.

Определите условие завершения и создайте цикл while с надписью while not condition do. Или, если вы действительно не хотите, чтобы это когда-либо заканчивалось, скажите while true do. А затем поместите логику вашего TCP-сервера в тело цикла.

РЕДАКТИРОВАТЬ: Реализация, которая не привязывает процессор на 100:

while true do
begin
  DoSomethingWithTCP;
  Sleep(0); 
end;

Вызов Sleep (0) возвращает процессор обратно в Windows для остальной части временного интервала, что предотвращает привязку процессора к 100. Каждый временной интервал длится около 16 миллисекунд, и если все, что вы делаете в Основной поток получает сообщения и передает их другим потокам, этого должно быть более чем достаточно, если вы не испытываете очень большую нагрузку.

0 голосов
/ 29 июля 2013
program YourConsoleProgram;

uses
  System.SysUtils,
  Winapi.Windows;

var
  Msg: TMsg;
  bRet: LongBool;

begin
  try
    { your program logic here }
    { start your own threads, tcp servers, etc. }

    // And this is Win32 Native Console Message Loop:
    repeat
      bRet := Winapi.Windows.GetMessage(Msg, 0, 0, 0);

      if Int32(bRet) = -1 then
      begin
        // Error
        Break;
      end
      else
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
     end;
   until not bRet;
 except
    on E: Exception do
    begin
      // do something with exception
      Writeln(E.Classname, ': ', E.Message);
    end;
  end;
end.
0 голосов
/ 07 апреля 2010

Вы можете использовать модуль SyncObjs и его классы, такие как TEvent, чтобы держать его в ожидании и быть открытым до тех пор, пока объект (ы) Event не получит сигнал от ваших потоков Indy.

...