如果有人想知道,解決方案實施起來相當簡單。我們現在有一個工作時間時鐘[0:00],在客戶端應用程序等待DataSnap服務器處理請求時增加。實質上,這就是我們所做的。 (特別感謝那些誰分享他們的解決方案 - 這幫助指導我的想法)
服務器生成的類(ProxyMethods)必須在VCL線程創建,但在一個單獨的線程中執行。要做到這一點,我們創建了一個ProxyMethods包裝類和ProxyMehtods線程類(所有這些都是人爲的這個例子,但仍說明了流量):
ProxyMethods.pas
...
type
TServerMethodsClient = class(TDSAdminClient)
private
FGetDataCommand: TDBXCommand;
public
...
function GetData(Param1: string; Param2: string): string;
...
end;
ProxyWrapper.pas
...
type
TServerMethodsWrapper = class(TServerMethodsClient)
private
FParam1: string;
FParam2: string;
FResult: string;
public
constructor Create; reintroduce;
procedure GetData(Param1: string; Param2: string);
procedure _Execute;
function GetResult: string;
end;
TServerMethodsThread = class(TThread)
private
FServerMethodsWrapper: TServerMethodsWrapper;
protected
procedure Execute; override;
public
constructor Create(ServerMethodsWrapper: TServerMethodsWrapper);
end;
implementation
constructor TServerMethodsWrapper.Create;
begin
inherited Create(ASQLServerConnection.DBXConnection, True);
end;
procedure TServerMethodsWrapper.GetData(Param1: string; Param2: string);
begin
FParam1 := Param1;
FParam2 := Param2;
end;
procedure TServerMethodsWrapper._Execute;
begin
FResult := inherited GetData(FParam1, FParam2);
end;
function TServerMethodsWrapper.GetResult: string;
begin
Result := FResult;
end;
constructor TServerMethodsThread.Create(ServerMethodsWrapper: TServerMethodsWrapper);
begin
FServerMethodsWrapper := ServerMethodsWrapper;
FreeOnTerminate := False;
inherited Create(False);
end;
procedure TServerMethodsThread.Execute;
begin
FServerMethodsWrapper._Execute;
end;
你可以請參閱我們將ProxyMethod的執行分爲兩步。第一步是將參數的值存儲在私有變量中。這允許_Execute()
方法具有執行實際ProxyMethods方法時需要知道的所有內容,其結果存儲在FResult
中供以後檢索。
如果ProxyMethods類具有多個函數,那麼在調用方法來設置私有變量時,您可以輕鬆地包裝每個方法並設置一個內部變量(例如,FProcID
)。這樣_Execute()
方法可以使用FProcID
來知道要執行哪個ProxyMethod ...
您可能想知道爲什麼線程不能自行釋放。原因是當線程自行清理時,我無法消除「線程錯誤:句柄無效(6)」錯誤。
調用包裝類的代碼如下所示:
var
smw: TServerMethodsWrapper;
val: string;
begin
...
smw := TServerMethodsWrapper.Create;
try
smw.GetData('value1', 'value2');
// start timer here
with TServerMethodsThread.Create(smw) do
begin
WaitFor;
Free;
end;
// stop/reset timer here
val := smw.GetResult;
finally
FreeAndNil(smw);
end;
...
end;
的WaitFor
掛起代碼執行,直到ProxyMethods線程完成。這是必要的,因爲smw.GetResult
將不會返回所需的值,直到線程完成執行。在代理執行線程繁忙時使經過時間的時鐘[0:00]遞增的關鍵是使用TJvThreadTimer
來更新UI。即使在單獨的線程中執行ProxyMethod,TTimer
也不起作用,因爲VCL線程正在等待WaitFor
,所以TTimer.OnTimer()
直到完成WaitFor
纔會執行。
信息上的TJvTheadTimer.OnTimer()
代碼看起來是這樣,這將更新應用程序的狀態欄:
var
sec: Integer;
begin
sec := DateUtils.SecondsBetween(Now, FBusyStart);
StatusBar1.Panels[0].Text := Format('%d:%.2d', [sec div 60, sec mod 60]);
StatusBar1.Repaint;
end;
這就是我的想法。你會認爲DataSnap已經存在了多長時間,會有內置的東西來處理UI繁忙狀態或者什麼...... DataSnap也缺少一個回調來提示UI有多少數據已經被傳輸,所以UI可以爲大數據檢索/推送實施進度指示器。 – 2012-03-01 21:01:47
(將此標記爲'正確答案',因爲解決方案可以採用任何形式 - 下面的答案只是可能性而已。太糟糕了,您不能將多於'一個'的答案標記爲'正確'。) – 2012-03-05 18:23:47