2013-10-30 82 views
1

對OrganizationServiceProxy對象調用.Dispose()會產生什麼樣的影響?爲什麼要調用OrganizationServiceProxy.Dispose()?

有時,在測試期間,代碼崩潰之前,可以丟棄對象;這是否意味着一個服務渠道是永恆的?

我有關於OrganizationServiceContext的相同問題,我一直沒有處理,直到今天讀this

/* Synchronizes with CRM * */ 
    public class CRMSync 
    { 
     [ThreadStatic] // ThreadStatic ensures that each thread gets a copy of these fields 
     private static OrganizationServiceProxy service; 
     [ThreadStatic] 
     private static Context linq; 
     /* Tries to connect to CRM and return false if failure - credentials arguments */ 
     private bool Connect(string username = @"username", string password = "password", string uri = @"orgUrl/XRMServices/2011/Organization.svc") 
     { 
      try 
      { 
       var cred = new ClientCredentials(); 
       cred.UserName.UserName = username; 
       cred.UserName.Password = password; 
       service = new OrganizationServiceProxy(new Uri(uri), null, cred, null); 
       service.EnableProxyTypes(); // this has to happen to allow LINQ early bound queries 
       linq = new Context(service); 
       var who = new Microsoft.Crm.Sdk.Messages.WhoAmIRequest(); // used to test the connection 
       var whoResponse = (Microsoft.Crm.Sdk.Messages.WhoAmIResponse)service.Execute(who); // this fails if not connected  
      } 
      catch (Exception e) 
      { 
       Log(e.Message); // Write to Event Log 
       return false; 
      } 
      return true; 
     } 
    } 

是否有另一種方式,使用多種方法相同OrganizationServiceContext和OrganizationServiceProxy?

我打算使用此析構函數處置OrganizationServiceProxy和OrganizationServiceContext:

~CRMSync() 
    { 
     if (service != null) 
      service.Dispose(); 
     if(linq!=null) 
      linq.Dispose(); 
    } 

編輯

這是ONSTART

/* Called by CRMAUX.OnStart when it is time to start the service */ 
    public async void Start() 
    { 
     this.ProcessCSVFiles(); // Creates a ThreadPool thread that processes some CSV files 
     this.ProcessCases(); // Imports cases into CRM from a db (on this thread) 
     var freq = 0; 
     ConfigurationManager.RefreshSection("appSettings"); 
     var parse = int.TryParse(ConfigurationManager.AppSettings["Frequency"], out freq); 
     await System.Threading.Tasks.Task.Delay((parse) ? freq * 1000 * 60 : 15000 * 60); // 15 minutes default or user defined 
     Start(); // Start again after the wait above 
    } 

由服務調用的方法這是Windows服務

public partial class CRMAUX : ServiceBase 
{ 
    private CRMSync crmSync; 
    public CRMAUX() 
    { 
     InitializeComponent(); 
    } 
    protected override void OnStart(string[] args) 
    { 
     ConfigurationManager.RefreshSection("userSettings"); // Get the current config file so that the cached one is not useds 
     if (TestConfigurationFile()) 
     { 
      crmSync = new CRMSync(); 
      Thread main = new Thread(crmSync.Start); 
      main.IsBackground = true; 
      main.Start(); 
     } 
     else //The configuration file is bad 
     { 
      Stop(); // inherited form ServiceBase 
      return; 
     } 
    } 
    protected override void OnStop() 
    {    
    } 
    /* Checks the configuration file for the necessary keys */ 
    private bool TestConfigurationFile()... 
} 

回答

2

OrganizationServiceProxy是利用非託管資源(套接字等)的WCF頻道的包裝。

實現IDisposable的類(我們的代理)基本上聲明它將訪問非託管資源,因此應該在完成時明確告訴它,而不是僅僅讓它超出範圍。這將允許它釋放這些資源的句柄並將它們釋放出來供其他地方使用。不幸的是我們的代碼不是服務器上運行的唯一東西!

非託管資源是有限且昂貴的(SQL連接是典型示例)。如果你的代碼正確執行,但你沒有明確地調用dispose,那麼清理這些資源將是非確定性的,這是一種奇怪的方式,稱垃圾回收器只會「最終」調用這些被管理對象的處置方式,反過來說清理他們所持有的非託管資源。這會損害您的應用程序的可伸縮性以及運行在可能與您競爭這些資源的相同硬件上的任何其他服務。這是最好的情況,如果在獲取這些資源之後堆棧中的任何一點發生異常,它們將不會被釋放,從而導致內存泄漏,並且可用於其他地方的資源更少。

在using語句中包裝你的代碼是語法糖,因爲這會編譯到代理被包裝在try/finally中,並在終端中調用dispose。

在跨多種方法使用代理/上下文方面,您應該查看工作單元模式。OrganizationServiceContext就是這樣的,你可以在請求過程中應用更改(可能跨多個方法調用),然後在完成時提交給數據存儲(CRM),在我們的案例中使用context.SaveChanges()

您使用此代碼的位置在哪裏,因爲我很想知道要使用[ThreadStatic]屬性來獲得什麼?如果它位於IIS託管的應用程序中,我認爲您不會看到任何好處,因爲您不管理線程池,所以代理仍然只有一個匹配HttpRequest的生存期。如果是這種情況,有幾種更好的方式來管理這些對象的生命週期,依賴注入框架和一個明顯的生命週期行爲。

+0

Windows服務應用程序創建CRMSync對象並調用CRMSync.Start()。 Start()調用一個方法創建一個新的線程,該線程從csv中提取數據; Start()也調用一個將數據庫中的案例推送到CRM中的方法。我會添加更多的代碼;你認爲有沒有更好的方法來做到這一點?我正在考慮擺脫私有成員,只使用包裝在使用中的本地OrganizationServiceContext和OrganizationServiceProxy變量。 – Bvrce

+1

我會用後者去使用非靜態實例。由於身份驗證,代理上的昂貴操作正在旋轉初始連接。我首先要測量它是否是性能瓶頸。如果你想增加導入的吞吐量,你可以看看使用任務並行庫(.NET 4.5中的async/await)。 –

0

如果您的應用程序崩潰,操作系統將自動收回您的所有資源,即關閉所有網絡端口,文件等。因此沒有任何東西會永遠打開。當然,在服務器端,如果處理不當並且應用程序在請求中間崩潰,可能會發生意想不到的情況。但這就是交易的目的,這樣服務器數據的狀態總是一致的。