sendasync邮件功能,你看到任何潜在的内存泄漏?

时间:2009-07-21 18:59:30

标签: vb.net smtp

我将该代码运行到Windows服务中,并且该服务似乎有内存泄漏,肯定是错误的。

在查看整个代码之后,我认为它可能在其中一个函数中,但我似乎无法找到它可能的位置。

任何人都可以看看,如果出现问题可以让我知道吗?

感谢您提供任何帮助。

Public Function sendEmail(Optional ByVal msg As String = "") As Boolean
    Dim mailSent As Boolean = False
    Dim mail As Net.Mail.MailMessage = Nothing
    Dim smtp As Net.Mail.SmtpClient = Nothing

    Try
        mail = New Net.Mail.MailMessage
        mail.From = New Net.Mail.MailAddress("myemail@myaddress.com")
        mail.Priority = Net.Mail.MailPriority.High
        mail.To.Add("1@1.1")
        mail.To.Add("2@1.1")
        mail.To.Add("3@1.1")
        mail.Subject = "test"
        mail.Body = msg
        Dim stream As IO.MemoryStream = createReport(Of IO.MemoryStream)()
        mail.Attachments.Add(New Net.Mail.Attachment(stream, "Report.html", "text/html"))

        smtp = New Net.Mail.SmtpClient("my.smtp.server")
        AddHandler smtp.SendCompleted, AddressOf SendCompletedCallback
        smtp.SendAsync(mail, mail)
        mailSent = True
    Catch ex As Exception
        Debug.Print(ex.Message)
    End Try

    If mail IsNot Nothing Then
        mail = Nothing
    End If

    If smtp IsNot Nothing Then
        smtp = Nothing
    End If

    Return mailSent
End Function

Private Sub SendCompletedCallback(ByVal sender As Object, ByVal e As ComponentModel.AsyncCompletedEventArgs)

    Try
        Dim i As Integer
        Dim mail As Net.Mail.MailMessage = CType(e.UserState, Net.Mail.MailMessage)
        If e.Cancelled Then
            Throw New Exception("Send mail got cancelled")
        ElseIf e.Error IsNot Nothing Then
            Throw e.Error
        End If
        For i = (mail.Attachments.Count - 1) To 0 Step -1
            mail.Attachments(i).Dispose()
        Next
        mail.Dispose()
        RemoveHandler CType(sender, Net.Mail.SmtpClient).SendCompleted, AddressOf SendCompletedCallback
    Catch ex As Exception
        Debug.Print(ex.Message)
    End Try
End Sub


Public Function createReport(Of dataType)() As dataType
    Dim result As Object = Nothing

    Dim ds As DataSet = Nothing
    Dim xmlDoc As Xml.XmlDocument = Nothing
    Dim xslTran As Xml.Xsl.XslCompiledTransform = Nothing

    Try
        Dim i As Integer


        ds = New dsEventLog ''dataset
        If IO.File.Exists("c:\myxmlfile") Then
            ds.Tables(0).ReadXml("c:\myxmlfile")
            For i = ds.Tables(0).Rows.Count - 1 To 0 Step -1
                If CDate(ds.Tables(0).Rows(i).Item("LocalTime")) < Now.AddDays(-5) Then
                    ds.Tables(0).Rows.RemoveAt(i)
                End If
            Next
        End If

        xmlDoc = New Xml.XmlDataDocument(ds)
        xslTran = New Xml.Xsl.XslCompiledTransform
        xslTran.Load("c:\myxslfile")

        If GetType(dataType) Is GetType(String) Then
            'doesn't matter
        ElseIf GetType(dataType) Is GetType(IO.MemoryStream) Then
            Dim stream = New IO.MemoryStream
            Dim sw As IO.StreamWriter = New IO.StreamWriter(stream)
            xslTran.Transform(xmlDoc, Nothing, sw)
            stream.Position = 0

            result = stream

            sw = Nothing
            stream = Nothing
        Else
            Throw New Exception("Incorrect ""Of dataType"" used!")
        End If
    Catch ex As Exception
        Debug.Print(ex.Message)
    End Try

    If ds IsNot Nothing Then
        ds.Dispose()
    End If
    ds = Nothing

    xslTran = Nothing
    xmlDoc = Nothing

    Return CType(result, dataType)
End Function

1 个答案:

答案 0 :(得分:0)

您应该通过调用Dispose方法处理内存流。您还应该处理任何实现IDisposable的类的对象以释放非托管内存。

此外,您不必将变量设置为Nothing。这实际上可以将内存中的对象保留得比它们更长。

修改

如果我没有弄错,附件就会被处理掉,而不是流本身......

此外,如果您查看example on MSDN,邮件将在主代码中处理,而不是在回调中。

其他问题:如果无法发送邮件,则不会调用Dispose。如果有例外,您也不会调用dispose。您应该将Dispose调用放在finally块中,以便在所有情况下都处理非托管资源。或者甚至更好,尽可能使用Using blocks