Delphi/C++Builder 2010加入了回叫機制, 我也在2009年的部落格文章中說明了如何使用Delphi/C++Builder 2010的回叫功. 然而Delphi/C++Builder XE又再次強化了回叫機制, 讓這個功能更為強大和完善, 由於XE版的回叫機制提供了眾多新的功能, 因此我想藉由這篇文章說明一下如何使用XE版的回叫機制, 雖然我無法一次把所有的功能寫完, 但起個頭還是很有用的. DataSnap XE在原有的基礎回叫機制之上加入了許多強大的新功能,從DataSnap XE開始開發人員可以使用下面的回叫功能:
- 用戶端可向伺服端註冊回叫通道,如此一來伺服器可以一次回叫所有在同回叫通道中所有註冊的用戶端回叫函式
- 用戶端可以同時註冊多個不同的回叫通道
- 用戶端可以藉由回叫通道呼叫不同的用戶端
- 新增回叫元件以幫助開發人員簡化開發回叫機制
DataSnap XE新的回叫功能雖然很多,但使用起來仍然相當的容易,下面說明了如何使用這些DataSnap XE新的回叫功能的基本步驟:
- 用戶端使用TDSClientCallbackChannelManager向伺服器註冊一個回叫通道
- 伺服器使用TDSServer元件的BroadcastMessage方法回叫所有註冊的用戶端
當然,開發人員可以更進一步的使用DataSnap XE進階的回叫功能,不過在那之前也許我們應該先說明數個範例讓讀者瞭解如何使用這些基本的步驟。 開發回叫DataSnap伺服器 在Delphi整合發展環境中建立一個DataSnap Server專案:
function BroadcastMessage(const ChannelName: String; const Msg: TJSONValue; const ArgType: Integer = TDBXCallback.ArgJson): boolean; overload;
function BroadcastMessage(const ChannelName: String; const CallbackId: String; const Msg: TJSONValue; const ArgType: Integer = TDBXCallback.ArgJson): boolean; overload;
复制代码
這兩個BroadcastMessage方法的差異在於上述第一個BroadcastMessage可以傳遞訊息給它第一個參數ChannelName指定的通道中所有的回叫用戶端,而第二個BroadcastMessage方法則是只傳遞訊息給它第一個參數ChannelName指定的通道中由第二個參數CallbackId指定的回叫用戶端,最後這個兩個BroadcastMessage方法傳遞給用戶端的訊息則由第二個參數Msg封裝。 瞭解了如何使用BroadcastMessage方法之後,我們就可以看看如何把DataSnap伺服器中於TMemo元件中輸入的訊息傳遞給回叫用戶端。現在為主表單中的TMemo元件實作OnChange事件處理函式如下:
001 procedure TForm17.mmMessageChange(Sender: TObject);
002 var
003 vMessage : TJSONString;
004 begin
005 vMessage := TJSONString.Create(mmMessage.Lines.Text);
006 ServerContainer5.DSServer1.BroadcastMessage(DEMOChannel, vMessage);
007 end;
复制代码
在005行我們把輸入於TMemo(mmMessage)中的資訊以TJSONString物件封裝,然後在006行藉由呼叫ServerContainer中的TDSServer元件的BroadcastMessage方法傳遞給所有註冊的用戶端。但誰是註冊的用戶端呢?請看BroadcastMessage的第一個參數DEMOChannel,這代表DataSnap伺服器會傳遞資訊給所有在DEMOChannel通道中註冊的用戶端。而DEMOChannel是一個通道的名稱,我們在DataSnap伺服器中定義它如下:
const
DEMOChannel = ‘DemoChannel’;
复制代码
因此用戶端只要使用這個名稱向伺服器註冊回叫通道的話,就可以讓DataSnap伺服器回叫用戶端,當然也用戶端可以先向伺服器查詢已經定義在DataSnap伺服器中的回叫通道名稱,或是由用戶端自行在DataSnap伺服器中建立指定名稱的回叫通道。 由於回叫用戶端是向DataSnap伺服器中指定名稱的回叫通道註冊,而且每一個用戶端都使用一個特定的回叫識別ID來代表,因此我們也可以藉由TDSServer元件來查詢某一個名稱的回叫通道中所有註冊的用戶端回叫識別ID。 此範例DataSnap伺服器主表單中的『列出所有回叫識別』按鈕的OnClick事件處理函式就可以在主表單上方的TListBox中列出特定回叫通道中所有的用戶端回叫識別ID,下面就是它的OnClick實作程式碼:
001 procedure TForm17.Button1Click(Sender: TObject);
002 var
003 aIdList : TList<String>;
004 sId : String;
005 begin
006 aIdList := ServerContainer5.DSServer1.GetAllChannelCallbackId(DEMOChannel);
007 try
008 for sId in aIdList do
009 ListBox1.Items.Add(sId);
010 finally
011 aIdList.Free;
012 end
013 end;
复制代码
GetAllChannelCallbackId方法會回傳TList<String>型態的執行結果,其中即包含了所有在此通道名稱中註冊的用戶端回叫識別ID,因此在006行藉由TDSServer元件呼叫GetAllChannelCallbackId之後,就可以取得到在DEMOChannel中註冊的識別ID,接著從008行到012行就把這些識別ID顯示在主表單的TListBox中。 現在請編譯並且執行此範例DataSnap伺服器,接著我們就可以實作回叫用戶端了,首先讓我們先說明如何建立Windows應用程式型態的用戶端,接著再說明如何建立瀏覽器型態的用戶端。
開發回叫DataSnap用戶端在專案管理員中再建立一個VCL Form應用程式專案,並且在其中放入TSQLConnection,TDSClientCallbackChannelManager,TMemo,兩個TButton元件,如下圖所示。其中TSQLConnection是連結上一小節的範例DataSnap伺服器,而TDSClientCallbackChannelManager則是使用來向DataSnap伺服器註冊回叫用戶端的元件。
接著設定TDSClientCallbackChannelManager特性值如下:
特性名稱 |
特性值 |
ChannelName |
DemoChannel |
CommunicationProtocol |
tcp/ip |
DSHostname |
localhost |
DSPort |
211 |
Name |
DemoChannelManager |
設定TDSClientCallbackChannelManager的ChannelName特性值為DemoChannel是因為前面範例DataSnap伺服器使用的通道名稱就是DemoChannel,而且前面範例DataSnap伺服器是支援TCP/IP通訊協定和使用211通信埠,因此我們需要設定TDSClientCallbackChannelManager相對應的特性值,下圖顯示了在物件檢視器中設定TDSClientCallbackChannelManager元件的特性值:
設定好TDSClientCallbackChannelManager元件之後,我們就可以看看用戶端主表單中的『啟動回叫功能』按鈕的實作程式碼了:
001 procedure TfmMainForm.btnStartClick(Sender: TObject);
002 begin
003 SetupTask;
004 EnableDisableButtons(False, True);
005 DemoChannelManager.RegisterCallback(callbackId, TDemoCallback.Create)
006 end;
007
008 procedure TfmMainForm.SetupTask;
009 begin
010 if not scnnCallbackServer.Connected then
011 begin
012 scnnCallbackServer.Connected := True;
013 end;
014 callbackId := DateTimeToStr(Now);
015 Self.Caption := callbackId;
016 end;
复制代码
在btnStartClick事件處理函式中先於003行呼叫SetupTask方法以開啟TSQLConnection元件連結範例DataSnap伺服器,並且在014行根據目前的時間建立一個獨特的識別ID,callbackId。最後在005行呼叫TDSClientCallbackChannelManager元件的RegisterCallback方法向範例DataSnap伺服器註冊這個回叫用戶端。 TDSClientCallbackChannelManager元件的RegisterCallback方法原型定義如下:
function RegisterCallback(const CallbackId: String; const Callback: TDBXCallback): boolean; overload;
复制代码
RegisterCallback接受兩個參數,第一個是每一個回叫用戶端的識別ID,第二個參數則是型態為TDBXCallback的物件,在前面的小節中我們已經解釋過TDBXCallback類別,因此在這裡我們需要建立一個從TDBXCallback衍生類別的物件,在這個衍生類別中我們需要複載虛擬方法Execute,如此一來範例DataSnap伺服器就可以藉由呼叫複載虛的擬方法Execute來呼叫到用戶端。 由於我們在上面的005行是傳遞TDemoCallback物件給RegisterCallback方法,因此我們需要在這個範例用戶端應用程式中定義和實作TDemoCallback類別,它需要從TDBXCallback繼承下來:
type
TDemoCallback = class(TDBXCallback)
public
constructor Create;
function Execute(const Arg: TJSONValue): TJSONValue; override;
end;
复制代码
TDemoCallback需要實作虛擬方法Execute,當DataSnap伺服器回叫用戶端時就會執行虛擬方法Execute。由於在這個範例中我們希望範例DataSnap伺服器在TMemo中輸入的資訊能夠立刻顯示在用戶端,因此我們實作虛擬方法Execute如下:
001 function TDemoCallback.Execute(const Arg: TJSONValue): TJSONValue;
002 var
003 sDemoMessage : String;
004 begin
005 Result := TJSONTrue.Create;
006
007 if (Arg is TJSONString) then
008 begin
009 sDemoMessage := TJSONString(Arg).Value;
010 TThread.Synchronize(nil,
011 procedure
012 begin
013 fmMainForm.mmDemoMessage.Lines.Text := sDemoMessage;
014 end
015 );
016 end;
017 end;
复制代码
當DataSnap伺服器藉由回叫功能呼叫用戶端複載的Execute時,DataSnap伺服器可以把伺服端傳遞到用戶端的資訊封裝在Execute的參數Arg中。由於在前面的範例DataSnap伺服器是把在伺服端TMemo中的資訊封裝成TJSONString傳遞到用戶端,因此在007行先判斷伺服端傳遞來的是否是TJSONString型態,如果是的話,就00行取出伺服端傳遞來的資訊,接著由於我們需要把這個資訊顯示在用戶端主表單中的TMemo元件中,因此我們藉由呼叫TThread類別的類別方法Synchronize來更新用戶端的使用者介面(這是因為用戶端使用者介面的主執行緒和在背景的回叫執行緒是不同的,因此需要使用Synchronize來讓背景回叫執行緒更新主執行緒中的元件)。由於Synchronize定義了如下的原型:
class procedure TThread.Synchronize(AThread: TThread; AMethod: TThreadMethod);
复制代码
因此在上面的010行中我們直接使用匿名方法來更新主表單的TMemo元件。 最後當我們不再需要讓用戶端被回叫時,可以呼叫TDSClientCallbackChannelManager元件的UnregisterCallback方法並且傳遞用戶端識別ID,例如下面的程式碼就是主表單中『停止回叫功能』按鈕OnClick事件處理函式的實作程式碼:
procedure TfmMainForm.btnStopClick(Sender: TObject);
begin
-
六六分期app的软件客服如何联系?不知道吗?加qq群【895510560】即可!标题:六六分期
阅读:19232|2023-10-27
-
今天小编告诉大家如何处理win10系统火狐flash插件总是崩溃的问题,可能很多用户都不知
阅读:9997|2022-11-06
-
今天小编告诉大家如何对win10系统删除桌面回收站图标进行设置,可能很多用户都不知道
阅读:8331|2022-11-06
-
今天小编告诉大家如何对win10系统电脑设置节能降温的设置方法,想必大家都遇到过需要
阅读:8701|2022-11-06
-
我们在使用xp系统的过程中,经常需要对xp系统无线网络安装向导设置进行设置,可能很多
阅读:8646|2022-11-06
-
今天小编告诉大家如何处理win7系统玩cf老是与主机连接不稳定的问题,可能很多用户都不
阅读:9667|2022-11-06
-
电脑对日常生活的重要性小编就不多说了,可是一旦碰到win7系统设置cf烟雾头的问题,很
阅读:8631|2022-11-06
-
我们在日常使用电脑的时候,有的小伙伴们可能在打开应用的时候会遇见提示应用程序无法
阅读:8005|2022-11-06
-
今天小编告诉大家如何对win7系统打开vcf文件进行设置,可能很多用户都不知道怎么对win
阅读:8665|2022-11-06
-
今天小编告诉大家如何对win10系统s4开启USB调试模式进行设置,可能很多用户都不知道怎
阅读:7540|2022-11-06
|
|
请发表评论