gpt4 book ai didi

.net - 有时是否必须使用 COM 对象显式调用 gc.collect

转载 作者:行者123 更新时间:2023-12-03 02:11:22 28 4
gpt4 key购买 nike

这是函数:

        Private Sub LoadEmail()

Dim loSession As RDOSession = Nothing
Dim loMessages As RDOItems = Nothing

Try
moNDRs = New List(Of NonDeliveryRecord)
loSession = New Redemption.RDOSession
loSession.LogonExchangeMailbox(MailAccountName, MailServerName)
loMessages = loSession.GetDefaultFolder(rdoDefaultFolders.olFolderInbox).Items
Dim Counter = 0
For Each loMessage As RDOMail In loMessages
Counter += 1
moNDRs.Add(CreateNDRRecord(loMessage))
Marshal.ReleaseComObject(loMessage)
loMessage = Nothing
If Counter Mod 100 = 0 Then GC.Collect()
Next


Finally
If loSession IsNot Nothing Then
loSession.Logoff()
Marshal.FinalReleaseComObject(loSession)
loSession = Nothing
End If

If loMessages IsNot Nothing Then
Marshal.FinalReleaseComObject(loMessages)
loMessages = Nothing
End If

End Try

End Sub

上面使用的消息类是 Redemption 。如果您查看上面的函数,您将看到:

If Counter Mod 100 = 0 Then GC.Collect()

这就是我必须做的来解决我们遇到的问题。今天早上我一直在使用内存分析器(ants 和 dottrace),看看我是否能弄清楚任何事情,但到目前为止一切看起来都很好。我水平不低谁知道windgb的来龙去脉。

我收到的错误是:IMAPISession::OpenEntry 中的错误:MAPI_E_TOO_BIG

下面的代码中注释了我总是收到错误的行。我总是在大约 450 次迭代后收到错误。

这是处理 COM 对象时必须使用 gc.collect 的少数几次之一吗?

这是 CreateNDR 函数,其中包含发生错误的行:

        Public Function CreateNDRRecord(ByVal voMessage As RDOMail) As NonDeliveryRecord

Dim loItem As RDOReportItem = Nothing
Dim loMatches As MatchCollection = Nothing
Dim loNonDeliveryCode As NonDeliveryRecord = New NonDeliveryRecord
Dim lsMessage As String = String.Empty


Try
loNonDeliveryCode.IsBadMessage = False
loNonDeliveryCode.MailMessageId = voMessage.EntryID

'Debug.Print(voMessage.MessageClass.Equals("REPORT.IPM.Note.NDR").ToString())
If voMessage.MessageClass.Equals("REPORT.IPM.Note.NDR") Then 'error always happens here
loItem = CType(voMessage, RDOReportItem)
If voMessage.Recipients.Count <> 0 Then
loNonDeliveryCode.EmailAddress = voMessage.Recipients(1).Name
End If
loNonDeliveryCode.IsUndeliverable = True
lsMessage = loItem.ReportText

ElseIf voMessage.Subject.Contains(mconSeparator) Then
loNonDeliveryCode.EmailAddress = voMessage.Subject.Substring(voMessage.Subject.LastIndexOf(mconSeparator) + mconSeparator.Length)
loNonDeliveryCode.ErrorCode = String.Empty
loNonDeliveryCode.IsUndeliverable = True
lsMessage = voMessage.Body
End If

If loNonDeliveryCode.IsUndeliverable Then

loMatches = GetErrorType(lsMessage)

If loMatches.Count > 0 Then
loNonDeliveryCode.ErrorCode = loMatches(loMatches.Count - 1).Value
End If

Dim loNDRId = GetErrorCode(loNonDeliveryCode.ErrorCode)

If loNDRId.Count > 0 Then
loNonDeliveryCode.ErrorCodeId = CType(CType(loNDRId(0), DataRow).Item("NonDeliveryCodeId"), Integer)
loNonDeliveryCode.ErrorDescription = CType(CType(loNDRId(0), DataRow).Item("Description"), String)
loNonDeliveryCode.MarkAsInvalid = CType(CType(loNDRId(0), DataRow).Item("MarkAsInvalid"), Boolean)
Else
If voMessage.MessageClass.Equals("REPORT.IPM.Note.NDR") Then
loNonDeliveryCode.ErrorCode = String.Empty
loNDRId = GetErrorCode(loNonDeliveryCode.ErrorCode)
loNonDeliveryCode.ErrorCodeId = CType(CType(loNDRId(0), DataRow).Item("NonDeliveryCodeId"), Integer)
loNonDeliveryCode.ErrorDescription = CType(CType(loNDRId(0), DataRow).Item("Description"), String)
loNonDeliveryCode.MarkAsInvalid = CType(CType(loNDRId(0), DataRow).Item("MarkAsInvalid"), Boolean)
Else
loNonDeliveryCode.ErrorCode = String.Empty
loNonDeliveryCode.ErrorCodeId = 1
End If
End If

End If


Return loNonDeliveryCode

Catch Ex As Exception
loNonDeliveryCode.IsUndeliverable = False
loNonDeliveryCode.IsBadMessage = True
Return loNonDeliveryCode

Finally
If loItem IsNot Nothing Then
Marshal.FinalReleaseComObject(loItem)
loItem = Nothing
End If

If voMessage IsNot Nothing Then Marshal.ReleaseComObject(voMessage)

If loMatches IsNot Nothing Then
loMatches = Nothing
End If

End Try

最佳答案

在某些情况下,程序没有消耗足够的垃圾收集内存来调用终结器线程来清理资源。例如,Thread 类就是一个麻烦制造者。它消耗 5 个操作系统句柄,但没有 Dispose() 方法来提前释放它们。和您正在使用的 COM 组件类一样,CLR 为它们创建的托管包装器具有终结器,但不实现 IDisposable。用户程序无法有效或可靠地调用 Dispose() 的类示例。

GC.Collect() 就是针对这种情况而设计的。还要调用 GC.WaitForPendingFinalizers(),因为这是您真正想要发生的事情。

您对它的使用是正确且站得住脚的。你必须调整它。

关于.net - 有时是否必须使用 COM 对象显式调用 gc.collect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8933091/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com