2016-11-30 7 views
0

Windowsアプリケーションとモバイルアプリケーション間のデータを処理するためのdatasnapサーバーアプリケーションを構築しました。Delphiの特定の時間後にメソッドを停止するDatasnapサーバーアプリケーション

一つの方法は、しばらく時間がかかることができ、私は一定の時間(タイムアウト)した後、それを止めることができるようにしたいです。

どうすればこの問題を解決できますか?

+1

私は、あなたが「停止」を定義する必要があると思います。たとえば、サーバーメソッドがデータベースサーバーからのデータを待っているために時間がかかる場合は、メソッドがタイムアウトしたことをクライアントに伝えたいのですか、またはdbクエリを取り消したいのですか? – MartynA

+0

さて、私は、サーバーがその方法で何をしていても、サーバーの作成または実行を停止したいだけです。それで、通話は終了し、クライアントは続けることができます。 – Remi

+1

その場合、時間がかかるセカンダリスレッド(つまり、メソッドの実行スレッドに対して2番目のセカンダリスレッド)を実行し、セカンダリスレッドが長すぎる場合は、そのスレッドを終了します。 – MartynA

答えて

2

以下のコードは、サーバーメソッドにタイムアウト動作を提供する1つの方法を示しています。時間がかかりすぎることがあり

タスクは、サーバーの方法で起動 される二次スレッドで実行されます。このメソッドは、TSimpleEventオブジェクト(オンラインヘルプを参照)を使用して、 セカンダリスレッドが完了したサーバーメソッドのスレッドに信号を返すようにします。 Event.WaitForへのコールで指定する値(ミリ秒単位)は、コールがタイムアウトするまでの待機時間を定義します。 SimpleEventのWaitForの呼び出しがタイムアウトになった場合は、 のようなアクションをサーバーのクライアントに通知することができます。 WaitForの呼び出しがwsSignaledを返した場合、WaitForを呼び出すときに指定された期間が経過する前にDBThreadがEventオブジェクトに対してSetEventを呼び出す必要があることを意味します。

ところで、この例では、D7のために書かれたので、 シアトルのマイナーな適応が必要になることがあります。また、TFormの子孫を「サーバー」として使用しますが、原理は同じであるため、DataSnapサーバーメソッドでも同様に機能するはずです。

それはまさにそれが可能であるとどのようにそれを行うにはそれがある場合は、タスクがあるまさに依存するかどうかをので、あなたは、セカンダリスレッドでキックオフどんなタスクを停止する方法の問題に対処しません。そのため、おそらくDBThreadが完了するのを待ってサーバーメソッドを遅らせたくないという事実は、DBThreadを解放しようとはしませんが、現実の世界ではもちろんそうなります。

type 
    TServer = class; 

    TDBThread = class(TThread) 
    private 
    FServer: TServer; 
    FEvent: TSimpleEvent; 
    FCancelled : Boolean; 
    function GetCancelled: Boolean; 
    procedure SetCancelled(const Value: Boolean); 
    public 
    procedure Execute; override; 
    constructor Create(AServer : TServer); 
    property Server : TServer read FServer; 
    property Event : TSimpleEvent read FEvent; 
    property Cancelled : Boolean read GetCancelled write SetCancelled; 
    end; 

    TServer = class(TForm) 
    // ignore the fact that in this case, TServer is a descendant of TForm 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    private 
    protected 
    CS : TCriticalSection; 
    Event : TSimpleEvent; 
    public 
    procedure DoServerMethod; 
    end; 
[...] 

{ TDBThread } 

constructor TDBThread.Create(AServer: TServer); 
begin 
    inherited Create(True); // create suspended 
    FreeOnTerminate := False; 
    FServer := AServer; 
    FEvent := FServer.Event; 
end; 

procedure TDBThread.Execute; 
var 
    StartTime : Cardinal; 
begin 
    Cancelled := False; 
    // Following is for illustration ONLY, to simulate a process which takes time. 
    // Do not call Sleep() in a loop in a real thread 
    StartTime := GetTickCount; 
    repeat 
    Sleep(100); 
    until GetTickCount - StartTime > 5000; 
    if not Cancelled then begin 
    { TODO : Transfer result back to server thread } 
    Event.SetEvent; 
    end; 
end; 

function TDBThread.GetCancelled: Boolean; 
begin 
    FServer.CS.Enter; 
    try 
    Result := FCancelled; 
    finally 
    FServer.CS.Leave; 
    end; 
end; 

procedure TDBThread.SetCancelled(const Value: Boolean); 
begin 
    FServer.CS.Enter; 
    try 
    FCancelled := Value; 
    finally 
    FServer.CS.Leave; 
    end; 
end; 

procedure TServer.DoServerMethod; 
var 
    DBThread : TDBThread; 
    WaitResult : TWaitResult; 
begin 
    DBThread := TDBThread.Create(Self); 
    DBThread.Resume; 
    WaitResult := Event.WaitFor(1000); 
    case WaitResult of 
    wrSignaled : begin 
     // the DBThread completed 
     ShowMessage('DBThread completed'); 
    end; 
    wrTimeOut : begin 
     // the DBThread time out 
     DBThread.Cancelled := True; 
     ShowMessage('DBThread timed out'); 
     // Maybe use PostThreadMessage here to tell the DBThread to abort (if possible) 
     // whatever task it is doing that has taken too long. 
    end; 
    end; {case} 
    { TODO : Terminate and dispose of the DBThread } 
end; 

procedure TServer.FormCreate(Sender: TObject); 
begin 
    CS := TCriticalSection.Create; 
    Event := TSimpleEvent.Create; 
end; 

procedure TServer.Button1Click(Sender: TObject); 
begin 
    DoServerMethod; 
end; 
+0

これはあなたのqに答えたのですか?あなたが私の答えについて理解していないことがありますか? – MartynA

関連する問題