2013-10-30 42 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

如果您的应用程序崩溃,操作系统将自动收回您的所有资源,即关闭所有网络端口,文件等。因此没有任何东西会永远打开。当然,在服务器端,如果处理不当并且应用程序在请求中间崩溃,可能会发生意想不到的情况。但这就是交易的目的,这样服务器数据的状态总是一致的。