如何使用OmniThreadLibrary从函数中获取布尔结果?

时间:2017-02-21 16:01:55

标签: multithreading delphi omnithreadlibrary

我有一个使用Delphi 10创建的Delphi(Windows)应用程序,它有一些我想要转换为使用线程的阻塞调用。不幸的是,这些不是程序,而是功能。 (有关如何从线程返回函数结果的信息似乎更加有限。)我正在尝试熟悉OmniThreadLibrary,因为它似乎是Delphi中最灵活和最受支持的线程库,但我有了解如何做到这一点的麻烦。

我已经能够使各种OmniThreadLibrary例程与程序一起使用,但是当我尝试设置一个函数时,我得到一个关于捕获结果的错误。当我使用OmniThreadLibrary的Future示例作为起点时,我可以让函数工作,但我无法弄清楚如何连接到事件监视器,如何从任务发送消息等等。所以,似乎好像无论我试图解决这个问题,我都会忽略一些事情。

目前,我的程序执行以下操作:

If myPing(IPAddress) then
begin
  //Do other things here…
end;

因为myPing是阻塞的,我实际上需要它等到myPing返回true才进一步处理之前,应用程序在此过程中变得缓慢。我想将myPing调用放在一个线程中,这将解决缓慢的问题,但我无法弄清楚如何使用OmniThreadLibrary以函数的形式做到这一点。 (除非我使用未来,在这种情况下我无法弄清楚如何连接到事件监视器。)

编辑1:自从我的原帖以来,我取得了一些进展。通过在函数之后添加Parallel.TaskConfig.MonitorWith(Form1.OmniEventMonitor1)到我的代码,我能够将事件监视器连接到Future。但是,我仍然无法弄清楚如何从Future函数中向该事件监视器发送消息。

编辑2:我现在有一些示例代码。我的第一次尝试与此类似:

function myPing(HostName: string): IOmniFuture<boolean>;
begin
  Result := Parallel.Future<boolean>(function: boolean
  begin
    Result := False;
    //Do actual ping here...  Set Result := True if successful.
  end
  );
end;

基本功能有效,但不允许我向TOmniEventMonitor发送任何消息。通过将代码更改为:

,我能够使该部分工作
function myPing(HostName: string): IOmniFuture<boolean>;
begin
  Result := Parallel.Future<boolean>(function: boolean
  begin
    Result := False;
    //Do actual ping here...  Set Result := True if successful.
  end,
  Parallel.TaskConfig.MonitorWith(Form1.OmniEventMonitor1)
  );
end;

现在,我可以成功监视OnTaskTerminated事件,但我仍然无法从任务向事件监视器发送消息。通过再次更改我的代码,我可以访问任务本身并使用task.Comm.Send()发送消息,但消息不会到达EventMonitor:

function myPing(HostName: string): IOmniFuture<boolean>;
begin
  Result := Parallel.Future<boolean>(function(const task: IOmniTask): boolean
  begin
    Result := False;
    //Do actual ping here...  Set Result := True if successful.
    task.Comm.Send(0,'Test 1');
  end,
  Parallel.TaskConfig.MonitorWith(Form1.OmniEventMonitor1)
  );
end;

1 个答案:

答案 0 :(得分:0)

这是一个关于如何从异步调用中检索函数结果的简单示例。它不使用&#34; OmniEventMonitor&#34;但是在异步调用返回后调用一个函数(&#34; Ping&#34;在PingU.pas中定义,但在这里不重要):

unit MainFormU;

interface

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

type
  TPingResultEvent = procedure (const bResult: Boolean) of object;

  TOnTerminateTestForm = class(TForm)
    LogMemo: TMemo;
    MainMenu: TMainMenu;
    PingMenu: TMenuItem;

    procedure PingMenuClick(Sender: TObject);

  private
    procedure BackgroundPing (const sServer: String;
                              const OnResult: TPingResultEvent);
    procedure PingResult (const bResult: Boolean);

  public
    { Public declarations }
  end;

var
  OnTerminateTestForm: TOnTerminateTestForm;

implementation

{$R *.dfm}

uses PingU, OtlParallel, OtlTaskControl;

procedure TOnTerminateTestForm.PingMenuClick (Sender: TObject);

var
    sServer : String;

begin
    if (InputQuery ('Ping computer', 'Computer name:', sServer)) then
        if (sServer <> '') then
        begin
            PingMenu.Enabled := false;
            LogMemo.Lines.Add (Format ('Pinging %s',[sServer]));
            BackgroundPing (sServer, PingResult);
        end; { if }
end; { TOnTerminateTestForm.PingMenuClick }

procedure TOnTerminateTestForm.BackgroundPing (const sServer: String;
                                               const OnResult: TPingResultEvent);

var
    bResult : Boolean;

begin
    Parallel.Async (
        procedure
        begin
            bResult := Ping (sServer);
        end,

        Parallel.TaskConfig.OnTerminated(
            procedure (const task: IOmniTaskControl)
            begin
                // executed in main thread after the async has finished
                if Assigned (OnResult) then
                    OnResult (bResult);
            end
      )
    );
end; { TOnTerminateTestForm.BackgroundPing }

procedure TOnTerminateTestForm.PingResult (const bResult: Boolean);
begin
    PingMenu.Enabled := true;
    LogMemo.Lines.Add ('Ping result = ' + BoolToStr (bResult, true));
end; { TOnTerminateTestForm.PingResult }

end.

代码来源:Get a function result asynchronously in Delphi using Omni Thread Library