- - PR -
[ASP.NET] GC.Collectの多用
1|2|3|4
次のページへ»
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-07-27 12:22
いつも拝見しています。
3〜4年程前に構築したシステムを運用しているのですが、未だ散発的に アプリケーションエラーが発生しています。 システム構成は ASP.NET(VB.NET) + OO4O + OracleR9.2 .NETFramework1.0 SP3 VisualStudio.NET2002 SP1 です。 OO4Oを使用している為、DB処理後にOracle接続用オブジェクトへ以下の 行為を行っています。 @Marshal.ReleaseComObjectを実行。 ANothingを代入。 BGC.Collect()を実行。 ⇒Bは実行しないとOracleへのセッションが無くならず溜まっていく 一方だったので実行しています。 散発的に発生しているエラーが発生している時のメッセージは 『オブジェクト参照がオブジェクト インスタンスに設定されていません。』 というものでもしかしたらOracleとの接続用オブジェクト(OraDatabaseや OraDynasetやOraSession)が破棄されているのでしょうか。 下記の情報を見る限りではGC.Collectを避けるとあるのですが、これを 実行しないとOracleとのセッションがなくなりません。 安全に処理を終らせる方法があればご教授ください。 http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetchapt05.asp http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetchapt07.asp | ||||||||
|
投稿日時: 2006-07-27 12:33
これは、(1) で漏れている参照があるからだと思います。 こちら情報からだけでは、具体的には示すことができませんが...
方法 -> まず、(1) の漏れがないかを調べることです。 ......というより、なぜ oo4o なのかが疑問です。 ODP.NET か、ADO.NET のテクノロジを使うべきだと思います。 何か理由があるのでしょうか? _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2006-07-27 12:45
あんまり .Net 系から、COM を頻繁に使うような事ってないんですが、ReleaseComObject で開放しなかったオブジェクトって、GC.Collect で回収される事ってあるんですか?
それは、さておき、そもそも Oracle が原因かどうかも切り分けできていなんですよね? Debug ビルドのファイルを配布して、どの行でエラーが出ているかを調べるのがいいような気がします。 | ||||||||
|
投稿日時: 2006-07-27 12:50
COM ラッパ オブジェクトが '未到達' になれば、回収はされます。(参照) _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2006-07-27 13:13
わちゃさんの仰るとおり、原因の切り分けが出来ていませんね。
も有効だと思いますが、現時点でスタックとレースぐらいはログを残していませんか? どのメソッドで起こっているのか分かれば、そのメソッド内の処理を全部チェックです。何ならここに全部貼ってもいいかも。 _________________ 囚人のジレンマな日々 | ||||||||
|
投稿日時: 2006-07-27 13:14
Marshal.ReleaseComObjectの返り値がちゃんと0になってるか
確認してみてはどうですか? .NET 2.0なら二度とそのCOMオブジェクトにアクセスしない場合は Marshal.FinalReleaseComObjectというのがあります。 これは内部マーシャリング回数を一気に0まで減らしてくれる ものです。 .NET 1.xならMarshal.ReleaseComObjectをwhile文でループさせて 内部マーシャリング回数を0にすれば同じことができます。 本来は参照元が責任をもってMarshal.ReleaseComObjectを呼び出す 方が良いのですが、全員が全員このような部分を理解しているとは 限らないので… | ||||||||
|
投稿日時: 2006-07-27 13:18
みなさんさっそくの回答ありがとうございます。
■漏れている参照というか使用しているものはOraSession、OraDatabase、 OraDynasetのみです。OraSessionは更新系以外は共通のコネクション プーリングを使用しています。が、再度確認をしてみます。 ちなみに現在Finallyで実行しているものを記述します。 Do Until lOraDatabase.Parameters.Count = 0 lOraDatabase.Parameters.Remove(0) Loop If Not lOraDynaset Is Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(lOraDynaset) End If lOraDynaset = Nothing System.Runtime.InteropServices.Marshal.ReleaseComObject(lOraDatabase) lOraDatabase = Nothing (OraSessionがあれば) System.Runtime.InteropServices.Marshal.ReleaseComObject(lOraSession) lOraSession= Nothing GC.Collect() ■OO4Oの採用ですが、3〜4年前に決定されたので・・・。 以降のシステムはADO.NETで作成をしています。 ■Oracleかどうかの完全は切り分けは行えていないのですが、Stack Traceより 確認したモジュールではOracleくらいしか操作をしていませんでした。 『Debug ビルドのファイルを配布』というのはASP.NETでも可能なのでしょうか。 | ||||||||
|
投稿日時: 2006-07-27 13:30
スタックトレースと該当の処理です。
■スタックトレース Error Message: オブジェクト参照がオブジェクト インスタンスに設定されていません。 Stack Trace: at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters) at System.RuntimeType.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) at Microsoft.VisualBasic.CompilerServices.VBBinder.InvokeMember(String name, BindingFlags invokeAttr, Type objType, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) at Microsoft.VisualBasic.CompilerServices.LateBinding.LateGet(Object o, Type objType, String name, Object[] args, String[] paramnames, Boolean[] CopyBack) at “作成プログラム”.LoginPage.CustomAuthenticate(String& UserName, String& PassWord) Source: mscorlib TargetSite: System.Object InvokeDispMethod(System.String, System.Reflection.BindingFlags, System.Object, System.Object[], Boolean[], Int32, System.String[]) ■該当の処理 Public Class LoginPage Inherits System.Web.UI.Page Private Function CustomAuthenticate(<引数1>, <引数2>) As String Dim lOraDatabase As OraDatabase Dim lOraDynaset As OraDynaset Dim lngFromPool As Integer lngFromPool = CInt(ConfigurationSettings.AppSettings("FromPool")) Try OraDatabase = Application("OraSession").GetDatabaseFromPool(lngFromPool) <SQL作成> <バインド変数設定> lOraDynaset = OraDatabase.DbCreateDynaset(“SQL”, dynOption.ORADYN_READONLY) If lOraDynaset.Fields(0).Value > 0 Then Return True Else Return False End If Catch exp As Exception <エラー処理> Finally Do Until lOraDatabase.Parameters.Count = 0 OraDatabase.Parameters.Remove(0) Loop If Not lOraDynaset Is Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(lOraDynaset) End If lOraDynaset = Nothing System.Runtime.InteropServices.Marshal.ReleaseComObject(lOraDatabase) lOraDatabase = Nothing GC.Collect() End Try End Function End Class 参考になればと思います。 |
1|2|3|4
次のページへ»