4

C#.NET 4.0 の使用

私の会社のアプリケーションでは、リソース ロッカーを使用して、レコードが同時に編集されないようにしています。データベースを使用して、ロックの開始時刻とロックを取得したユーザーを保存します。これは、たまたまデストラクタから呼び出される、リソース ロッカーでの dispose の次の (奇妙な?) 実装につながりました。

protected virtual void Dispose(bool disposing)
        {
            lock (this)
            {
                if (lockid.HasValue)
                {
                    this.RefreshDataButtonAction = null;
                    this.ReadOnlyButtonAction = null;

                try
                {
                    **Dictionary<string, object> parameters = new Dictionary<string, object>();
                    parameters.Add("@lockID", lockid.Value);
                    parameters.Add("@readsToDelete", null);
                    Object returnObject = dbio2.ExecuteScalar("usp_DeleteResourceLockReads", parameters);**

                    lockid = null;
                }
                catch (Exception ex)
                {
                    Logger.WriteError("ResourceLockingController", "DeleteResourceLocks", ex);
                }
                finally
                {
                    ((IDisposable)_staleResourcesForm).Dispose();
                    _staleResourcesForm = null;
                }
            }
        }
    }

データベース呼び出しからの奇妙な「ハンドルが初期化されていません」という例外をログに記録しているため、太字のセクションが心配です。Finalize() 中に新しいオブジェクトを作成するのは安全ではないことを他の場所で読みましたが、同じルールが dispose() に適用されますか? Dispose() 中に新しいオブジェクトを作成することに伴う副作用はありますか?

4

3 に答える 3

1

これはたまたまデストラクタから呼び出されます

それが本当の問題です。*dbio2" オブジェクト自体がファイナライズされていないと仮定することはできません。ファイナライズの順序は .NET では決定論的ではありません。結果は、説明したように見えます。dbase プロバイダーによって使用される内部ハンドルが解放されるため、"ハンドルは初期化されていません」という例外が予想されます。または、dbio2 オブジェクトがすでに破棄されています。

これは、プログラムの終了時に特に問題が発生する可能性があります。また、ファイナライザー スレッドの 2 秒のタイムアウトの場合にも問題が発生します。dbase 操作は簡単にそれ以上かかる場合があります。

これを行うためにファイナライザーに頼ることはできません。disposing引数を確認し、false の場合は dbio2.ExecuteScalar() メソッドを呼び出さないようにする必要があります。おそらく、デストラクタの有用性も終了します。

于 2013-10-17T18:23:53.200 に答える