1

OrganizationServiceProxy オブジェクトで .Dispose() を呼び出さないことの影響は何ですか?

テスト中に、オブジェクトを破棄する前にコードがクラッシュすることがあります。これは、サービスチャネルが永遠に開かれたままになっていることを意味しますか?

今日これを読むまで処分していなかった OrganizationServiceContext について同じ質問があります。

    /* 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()...
}
4

2 に答える 2

2

これOrganizationServiceProxyは、アンマネージ リソース (ソケットなど) を利用する WCF チャネルのラッパーです。

を実装するクラス (私たちのプロキシ)IDisposableは基本的に、アンマネージ リソースにアクセスすることを宣言しているため、単にスコープ外に出るのを許可するのではなく、終了時に明示的に伝える必要があります。これにより、それらのリソースへのハンドルを解放し、他の場所で使用できるように解放できます。残念ながら、サーバー上で実行されているのは私たちのコードだけではありません!

管理されていないリソースは有限であり、高価です (SQL 接続は典型的な例です)。コードが正しく実行されても明示的に dispose を呼び出さない場合、これらのリソースのクリーンアップは非決定論的になります。これは、ガベージ コレクターがそれらの管理対象オブジェクトに対してのみ dispose を「最終的に」呼び出すという派手な方法です。次に、保持している管理されていないリソースをクリーンアップします。これにより、アプリケーションのスケーラビリティや、同じハードウェア上で実行されている他のサービスがそれらのリソースをめぐって競合する可能性があります。これが最良のシナリオです。これらのリソースが取得された後にスタック内の任意の時点で例外が発生した場合、リソースは解放されず、メモリ リークが発生し、他の場所で使用できるリソースが少なくなります。

コードを using ステートメントでラップすることは、プロキシが try/finally でラップされ、dispose が finally で呼び出されるようにコンパイルされるため、シンタックス シュガーです。

複数のメソッドでプロキシ/コンテキストを使用するという点では、Unit of Work パターンを確認する必要があります。OrganizationServiceContext はまさにそれであり、リクエストの過程で (おそらく複数のメソッド呼び出しにわたって) 変更を適用し、完了したら最後にデータストア (CRM) に送信しますcontext.SaveChanges()

属性を使用して何を達成しようとしているのか知りたいので、このコードをどこで使用してい[ThreadStatic]ますか? IIS でホストされているアプリケーション内にある場合、スレッド プールを管理しないため、プロキシの有効期間はHttpRequest. この場合、これらのオブジェクトの有効期間を管理するためのより良い方法がいくつかあります。依存性注入フレームワークとHttpRequest有効期間の動作は明らかです。

于 2013-10-31T00:36:19.373 に答える
0

アプリがクラッシュした場合、オペレーティング システムは自動的にすべてのリソースを再利用します。つまり、すべてのネットワーク ポートやファイルなどを閉じます。したがって、何も永久に開いたままになることはありません。もちろん、サーバー側では、適切に処理されず、リクエストの途中でアプリがクラッシュすると、予期しない事態が発生する可能性があります。しかし、それがトランザクションの目的であり、サーバー データの状態は常に一貫しています。

于 2013-10-30T11:55:01.190 に答える