Windowsアプリケーションとモバイルアプリケーション間のデータを処理するためのdatasnapサーバーアプリケーションを構築しました。Delphiの特定の時間後にメソッドを停止するDatasnapサーバーアプリケーション
一つの方法は、しばらく時間がかかることができ、私は一定の時間(タイムアウト)した後、それを止めることができるようにしたいです。
どうすればこの問題を解決できますか?
Windowsアプリケーションとモバイルアプリケーション間のデータを処理するためのdatasnapサーバーアプリケーションを構築しました。Delphiの特定の時間後にメソッドを停止するDatasnapサーバーアプリケーション
一つの方法は、しばらく時間がかかることができ、私は一定の時間(タイムアウト)した後、それを止めることができるようにしたいです。
どうすればこの問題を解決できますか?
以下のコードは、サーバーメソッドにタイムアウト動作を提供する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;
これはあなたのqに答えたのですか?あなたが私の答えについて理解していないことがありますか? – MartynA
私は、あなたが「停止」を定義する必要があると思います。たとえば、サーバーメソッドがデータベースサーバーからのデータを待っているために時間がかかる場合は、メソッドがタイムアウトしたことをクライアントに伝えたいのですか、またはdbクエリを取り消したいのですか? – MartynA
さて、私は、サーバーがその方法で何をしていても、サーバーの作成または実行を停止したいだけです。それで、通話は終了し、クライアントは続けることができます。 – Remi
その場合、時間がかかるセカンダリスレッド(つまり、メソッドの実行スレッドに対して2番目のセカンダリスレッド)を実行し、セカンダリスレッドが長すぎる場合は、そのスレッドを終了します。 – MartynA