- PR -

[ASP.NET] GC.Collectの多用

投稿者投稿内容
未記入
会議室デビュー日: 2005/06/22
投稿数: 8
投稿日時: 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
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-07-27 12:33
引用:

未記入さんの書き込み (2006-07-27 12:22) より:

(1) Marshal.ReleaseComObjectを実行。
(2) Nothingを代入。
(3) GC.Collect()を実行。
 ⇒(3) は実行しないとOracleへのセッションが無くならず溜まっていく
 一方だったので実行しています。


これは、(1) で漏れている参照があるからだと思います。
こちら情報からだけでは、具体的には示すことができませんが...

引用:

安全に処理を終らせる方法があればご教授ください。


方法 -> まず、(1) の漏れがないかを調べることです。

......というより、なぜ oo4o なのかが疑問です。
ODP.NET か、ADO.NET のテクノロジを使うべきだと思います。

何か理由があるのでしょうか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
わちゃ
大ベテラン
会議室デビュー日: 2005/12/05
投稿数: 162
お住まい・勤務地: 東京
投稿日時: 2006-07-27 12:45
あんまり .Net 系から、COM を頻繁に使うような事ってないんですが、ReleaseComObject で開放しなかったオブジェクトって、GC.Collect で回収される事ってあるんですか?

それは、さておき、そもそも Oracle が原因かどうかも切り分けできていなんですよね?

Debug ビルドのファイルを配布して、どの行でエラーが出ているかを調べるのがいいような気がします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-07-27 12:50
引用:

わちゃさんの書き込み (2006-07-27 12:45) より:

あんまり .Net 系から、COM を頻繁に使うような事ってないんですが、ReleaseComObject で開放しなかったオブジェクトって、GC.Collect で回収される事ってあるんですか?


COM ラッパ オブジェクトが '未到達' になれば、回収はされます。(参照)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-07-27 13:13
わちゃさんの仰るとおり、原因の切り分けが出来ていませんね。
引用:

Debug ビルドのファイルを配布して、どの行でエラーが出ているかを調べるのがいいような気がします。


も有効だと思いますが、現時点でスタックとレースぐらいはログを残していませんか?
どのメソッドで起こっているのか分かれば、そのメソッド内の処理を全部チェックです。何ならここに全部貼ってもいいかも。
_________________
囚人のジレンマな日々
がんふぃーるど
ベテラン
会議室デビュー日: 2006/06/05
投稿数: 58
お住まい・勤務地: さいたま
投稿日時: 2006-07-27 13:14
Marshal.ReleaseComObjectの返り値がちゃんと0になってるか
確認してみてはどうですか?

.NET 2.0なら二度とそのCOMオブジェクトにアクセスしない場合は
Marshal.FinalReleaseComObjectというのがあります。
これは内部マーシャリング回数を一気に0まで減らしてくれる
ものです。
.NET 1.xならMarshal.ReleaseComObjectをwhile文でループさせて
内部マーシャリング回数を0にすれば同じことができます。
本来は参照元が責任をもってMarshal.ReleaseComObjectを呼び出す
方が良いのですが、全員が全員このような部分を理解しているとは
限らないので…
未記入
会議室デビュー日: 2005/06/22
投稿数: 8
投稿日時: 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でも可能なのでしょうか。
未記入
会議室デビュー日: 2005/06/22
投稿数: 8
投稿日時: 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

参考になればと思います。

スキルアップ/キャリアアップ(JOB@IT)