首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用OmniThreadLibrary从函数中获取布尔结果?

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

Stack Overflow用户
提问于 2017-02-22 00:01:55
回答 1查看 359关注 0票数 0

我有一个用Delphi10创建的Delphi (Windows)应用程序,它有一些阻塞调用,我想使用线程来转换。不幸的是,对我来说,这些不是过程,而是函数。(关于如何从线程返回函数结果的信息似乎要有限得多。)我正在努力熟悉OmniThreadLibrary,因为它似乎是Delphi中最灵活和最受支持的线程库,但我在理解如何做到这一点上遇到了麻烦。

我已经能够让各种OmniThreadLibrary例程与过程很好地协同工作,但是当我尝试设置一个函数时,我得到了一个关于捕获结果的错误。当我使用OmniThreadLibrary的Future示例作为起点时,我可以让函数工作,但我不知道如何连接到事件监视器,如何从任务发送消息等。因此,无论我试图以哪种方式解决这个问题,似乎都忽略了一些东西。

目前,我的程序是这样做的:

代码语言:javascript
复制
If myPing(IPAddress) then
begin
  //Do other things here…
end;

因为myPing正在阻塞,而我实际上需要等待它,直到myPing返回true才能进一步处理,所以应用程序在这个过程中变得缓慢。我想将myPing调用放在一个线程中,这样可以解决速度慢的问题,但我不知道如何使用OmniThreadLibrary以函数的形式实现这一点。(除非我使用的是future,在这种情况下,我不知道如何连接到事件监视程序。)

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

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

代码语言:javascript
复制
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发送任何消息。通过将代码更改为以下代码,我能够使该部分正常工作:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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;
EN

回答 1

Stack Overflow用户

发布于 2017-02-24 00:26:02

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

代码语言:javascript
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42372198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档