2017-02-21 10 views
0

Delphi 10を使用して作成したDelphi(Windows)アプリケーションで、スレッドを使用して変換したいブロッキングコールがいくつかあります。残念なことに私にとっては、これは手続きではなく機能です。 (そして、スレッドからの関数の結果を返す方法に関する情報は、はるかに限定されているように見えます)。OmniThreadLibraryはDelphiの最も柔軟性の高い、最もサポートされているスレッドライブラリですが、これを行う方法を理解することに問題があります。OmniThreadLibraryを使用して関数からブール値を取得するにはどうすればよいですか?

私は手順でうまく動作するために、様々なOmniThreadLibraryルーチンを取得することができたが、私は機能を設定しようとすると、私は結果をキャプチャに関するエラーが表示されます。 OmniThreadLibraryのFutureサンプルを出発点として使用すると、関数を呼び出せるようになりますが、イベントモニターへの接続方法、タスクからのメッセージの送信方法などは分かりません。私はこの問題をどのように解決しようとしても何かを見過ごしています。このプロセスの間に

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

myPingがブロックしている、と私は実際にmyPingは、さらに処理する前にtrueを返すまでは待つ必要があるため、アプリケーションは低迷を取得:

現在、私のプログラムは、このような何かを行います。 myPingの呼び出しをスレッドに入れて、低速問題を解決したいと思いますが、OmniThreadLibraryを使用して関数の形でこれを行う方法を理解できません。 (私はイベントモニタに接続する方法を見つけ出すことはできません、その場合には、将来を、使用しない限り。)

編集1:私のオリジナルのポストので、私は少し進歩を遂げています。関数の直後にParallel.TaskConfig.MonitorWith(Form1.OmniEventMonitor1)をコードに追加することで、Event Monitorを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にメッセージを送信することはできませんでした。私の最初の試みは、これと同様でした。私は成功しOnTaskTerminatedイベントを監視することができますが、私はまだタスクからイベントモニタにメッセージを送信することはできません、今

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; 

:私はこれにコードを変更することにより、作業その部分を取得することができました。再び私のコードを変更することにより、私は仕事自体にアクセスし、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; 
+0

それは(ただし、ここで重要なの、「Pingのは」PingU.pasで定義されている)「OmniEventMonitor」を使用する代わりに、非同期呼び出しが戻る一度関数を呼び出していません1つの方法は、OMNI Thread parallelを使用してpingを実行することです。特定のIPのpingが成功した場合は、開始アドレスとしてそのジョブにIPアドレスを渡す「その他のもの」を実行するための新しいジョブを作成します。 – SilverWarior

+1

パラレルパイプラインの例http://www.thedelphigeek.com/2010/11/multistage-processes-with.html – SilverWarior

+0

デルファイのバージョンは?どのプラットフォーム(Windowsまたはモバイル)ですか? –

答えて

0

ここで取得する方法についての簡単な例です関数は非同期呼び出しの結果になります。

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

オラフ、 これはかなり役に立ちました。ありがとうございました。今、私はまだ非同期部分からイベントモニターにメッセージを送信できません。あなたはそれを正しい方向に向けることができますか? (私はOmniThreadのドキュメントを見直していますが、私が見逃しているものは見ていません)。 – Various60

関連する問題