程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> DataSnap 2009 系列之三 (生命周期篇)

DataSnap 2009 系列之三 (生命周期篇)

編輯:Delphi

 本文示例源代碼或素材下載

  DataSnap 2009的服務器對象的生命周期依賴於DSServerClass組件的設置

  當DSServer啟動時從DSServerClass組件讀取LifeCycle屬性的值

  注意:LifeCycle的值由於在啟動時就已經讀取 啟動後再修改LifeCycle的值將沒有任何效果

  LifeCycle屬性的值可以是以下三種字符串之一

  1.Session

  該選項為默認設置

  每個連接都會建立一個獨立的服務器對象為客戶端提供服務,服務器對象在連接關閉後釋放

  因此多個客戶端訪問的是不同的服務器對象,是線程安全的

  2.Invocation

  對於每次服務端方法調用建立一個獨立的服務器對象為客戶端提供服務,服務器對象在調用結束後釋放

  這個同樣也是線程安全的

  但是每次調用都創建和釋放服務器對象對於頻繁調用的系統影響很大,如果把服務端對象用對象池管理配合此種方式將是個非常不錯的解決方案

  3.Server

  所有的客戶端使用同一個服務端對象,也就是該對象是單例的

  需要開發人員自己來進行同步的控制,不是線程安全的

  在服務端對象創建和釋放時將觸發DSServerClass的兩個重要的事件OnCreateInstance和OnDestroyInstance

  在這裡我們可以使用自定義創建和釋放服務器對象 同樣我們可以用於服務端對象池

  下面我們把上一次的DEMO稍微改動下來觀察下服務端對象的生命周期

  我們先將DSServer組件的AutoStart設置為False 然後拖上兩個Button分別完成Start和Stop的調用

procedure TMainForm.StartClick(Sender: TObject);
begin
  DSServer.Start;
end;

procedure TMainForm.StopClick(Sender: TObject);
begin
  DSServer.Stop;
end;

 在OnGetClass中記錄服務啟動時使用的生命周期

procedure TMainForm.DSServerClassGetClass(DSServerClass: TDSServerClass;
  var PersistentClass: TPersistentClass);
begin
  DSServerClass.LifeCycle := LifeCycles.Items.Strings[LifeCycles.ItemIndex];
  LogMessage(Memo, '生命周期:' + DSServerClass.LifeCycle);
  PersistentClass := TSM;
end;

  LifeCycles是一個TRadioGroup存放了生命周期使用的三個字符串

  最後在OnCreateInstance和OnDestroyInstance事件中記錄服務器對象的創建和釋放

procedure TMainForm.DSServerClassCreateInstance(
  DSCreateInstanceEventObject: TDSCreateInstanceEventObject);
begin
  LogMessage(Memo, '服務端對象創建');
end;

procedure TMainForm.DSServerClassDestroyInstance(
  DSDestroyInstanceEventObject: TDSDestroyInstanceEventObject);
begin
  LogMessage(Memo, '服務端對象釋放');
  //DSDestroyInstanceEventObject.ServerClassInstance.Free;
end;

  效果圖

DataSnap 2009 系列之三 (生命周期篇)

  圖片看不清楚?請點擊這裡查看原圖(大圖)。

  通過Demo我們可以明顯的看出三種生命周期的區別 注意切換生命周期需要先停止服務器再啟動

 但是在我們使用Invocation的時候 會造成內存洩露

  打開服務端的ReportMemoryLeaksOnShutdown 調用了兩次方法後關閉服務端可以看到如下提示

DataSnap 2009 系列之三 (生命周期篇)

  可以看到服務端對象並沒有釋放

  這裡需要我們通過在OnDestroyInstance手動釋放

DSDestroyInstanceEventObject.ServerClassInstance.Free;

  但是我們會發現內存洩露依然存在TDSProviderDataModuleAdapter依然沒有釋放

  這是由於DataSnap2009中繼承自TProviderDataModule的類都使用了適配器模式來支持舊的IAPPServer接口

  在服務端對象創建的過程TDSServerClass.CreateInstance中我們可以看到

if (Instance <> nil) and Instance.InheritsFrom(TProviderDataModule) then
  CreateInstanceEventObject.ServerClassInstance := TDSProviderDataModuleAdapter.Create(Instance);

  因此在服務端釋放的TDSServerClass.DestroyInstance中需要釋放TDSProviderDataModuleAdapter對象

    if DestroyInstanceEventObject.ServerClassInstance is TDSProviderDataModuleAdapter then
    begin
      Adapter := DestroyInstanceEventObject.ServerClassInstance as TDSProviderDataModuleAdapter;
      DestroyInstanceEventObject.ServerClassInstance := Adapter.FProviderDataModule;
      Adapter.FProviderDataModule := nil;
    end else
      Adapter := nil;

  當使用Invocation生命周期時 傳遞的ServerClassInstance並不是TDSProviderDataModuleAdapter的對象

  所以盡管我們手動釋放了我們的服務端對象 適配器對象任然造成了內存洩露




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved