Asp.net 使用System.Threading.ThreadPool时不包含任何内容的电子邮件

Asp.net 使用System.Threading.ThreadPool时不包含任何内容的电子邮件,asp.net,.net,multithreading,threadpool,system.net.mail,Asp.net,.net,Multithreading,Threadpool,System.net.mail,我在尝试使用Threading.ThreadPool发送电子邮件时遇到了一种奇怪的行为 这一做法已经奏效一年多了,但最近它宣布断断续续地发送没有内容的电子邮件。收件人和主题都很好,但是电子邮件的其余部分是空白的。代码方面没有任何更改(除了对其运行的服务器的Windows更新) 这是我正在使用的代码——有人建议我如何缩小问题发生的范围吗?在将电子邮件重新发送给声称收到空白电子邮件的人时,他们得到了很好的回复——它使用了与第一次发送的完全相同的代码 Sub生成电子邮件: Public Sub Em

我在尝试使用
Threading.ThreadPool
发送电子邮件时遇到了一种奇怪的行为

这一做法已经奏效一年多了,但最近它宣布断断续续地发送没有内容的电子邮件。收件人和主题都很好,但是电子邮件的其余部分是空白的。代码方面没有任何更改(除了对其运行的服务器的Windows更新)

这是我正在使用的代码——有人建议我如何缩小问题发生的范围吗?在将电子邮件重新发送给声称收到空白电子邮件的人时,他们得到了很好的回复——它使用了与第一次发送的完全相同的代码

Sub生成电子邮件:

 Public Sub EmailConfirmation(email As String,
                                 firstname As String,
                                 details As String)

        Try


            Dim embody As String = GlobalHelper.emailBody
            'static class which loads the email text at application load for use later.
            'This is a point of concern because it's obviously where the embody text is
            'is loaded, but the issue is intermittent and if there was a failure here surely
            'it would be caught by the 'try...catch' and a log of the error created (which has
            'never happened). I also ran an experiment for a while where if this string was 
            'empty then create a log entry. After receiving a complaint of a blank email
            'no error log was found.

            embody = Replace(embody, "[FirstName]", firstname)
            embody = Replace(embody, "[DATA]", details)


            'create the mail message
            Dim mail As New MailMessage()

            'set the addresses
            mail.From = New MailAddress("myemail@mydomain.com", "My Display Name")
            mail.To.Add(email)
            mail.IsBodyHtml = True

            'set the content
            mail.Subject = "Email Subject!"
            mail.Body = embody


            AddEmailToThreadPool(mail)

        Catch ex As Exception

        'if there is an error it is logged here. 

        End Try


    End Sub
Private Sub AddEmailToThreadPool(email As MailMessage)
        System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf sendEmail), email)
    End Sub
Private Sub sendEmail(stateinfo As Object)

        Dim email As MailMessage = CType(stateinfo, MailMessage)


        Try

            'send the message
            Dim smtp As New SmtpClient("mail.mydomain.com")
            smtp.Send(email)
        Catch ex As Exception
            'error is logged here.
        End Try

    End Sub
添加到线程池的子线程:

 Public Sub EmailConfirmation(email As String,
                                 firstname As String,
                                 details As String)

        Try


            Dim embody As String = GlobalHelper.emailBody
            'static class which loads the email text at application load for use later.
            'This is a point of concern because it's obviously where the embody text is
            'is loaded, but the issue is intermittent and if there was a failure here surely
            'it would be caught by the 'try...catch' and a log of the error created (which has
            'never happened). I also ran an experiment for a while where if this string was 
            'empty then create a log entry. After receiving a complaint of a blank email
            'no error log was found.

            embody = Replace(embody, "[FirstName]", firstname)
            embody = Replace(embody, "[DATA]", details)


            'create the mail message
            Dim mail As New MailMessage()

            'set the addresses
            mail.From = New MailAddress("myemail@mydomain.com", "My Display Name")
            mail.To.Add(email)
            mail.IsBodyHtml = True

            'set the content
            mail.Subject = "Email Subject!"
            mail.Body = embody


            AddEmailToThreadPool(mail)

        Catch ex As Exception

        'if there is an error it is logged here. 

        End Try


    End Sub
Private Sub AddEmailToThreadPool(email As MailMessage)
        System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf sendEmail), email)
    End Sub
Private Sub sendEmail(stateinfo As Object)

        Dim email As MailMessage = CType(stateinfo, MailMessage)


        Try

            'send the message
            Dim smtp As New SmtpClient("mail.mydomain.com")
            smtp.Send(email)
        Catch ex As Exception
            'error is logged here.
        End Try

    End Sub
发送电子邮件的子系统:

 Public Sub EmailConfirmation(email As String,
                                 firstname As String,
                                 details As String)

        Try


            Dim embody As String = GlobalHelper.emailBody
            'static class which loads the email text at application load for use later.
            'This is a point of concern because it's obviously where the embody text is
            'is loaded, but the issue is intermittent and if there was a failure here surely
            'it would be caught by the 'try...catch' and a log of the error created (which has
            'never happened). I also ran an experiment for a while where if this string was 
            'empty then create a log entry. After receiving a complaint of a blank email
            'no error log was found.

            embody = Replace(embody, "[FirstName]", firstname)
            embody = Replace(embody, "[DATA]", details)


            'create the mail message
            Dim mail As New MailMessage()

            'set the addresses
            mail.From = New MailAddress("myemail@mydomain.com", "My Display Name")
            mail.To.Add(email)
            mail.IsBodyHtml = True

            'set the content
            mail.Subject = "Email Subject!"
            mail.Body = embody


            AddEmailToThreadPool(mail)

        Catch ex As Exception

        'if there is an error it is logged here. 

        End Try


    End Sub
Private Sub AddEmailToThreadPool(email As MailMessage)
        System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf sendEmail), email)
    End Sub
Private Sub sendEmail(stateinfo As Object)

        Dim email As MailMessage = CType(stateinfo, MailMessage)


        Try

            'send the message
            Dim smtp As New SmtpClient("mail.mydomain.com")
            smtp.Send(email)
        Catch ex As Exception
            'error is logged here.
        End Try

    End Sub
我是从MSDN复制的

此类型的任何公共静态(在Visual Basic中共享)成员都是线程安全的。任何实例成员都不能保证线程安全


嗯,在修复了不正确的文档类型声明之后,我已经有将近一个月没有收到过任何关于空白电子邮件的投诉了。我将假设这解决了问题,尽管我不确定为什么


感谢您的所有输入/帮助。

通过验证程序运行
GlobalHelper.emailBody
返回的HTML。格式错误的HTML可能无法在浏览器中显示任何内容。您的邮件客户端是否已更改?身体不能被正确地渲染吗?您是否记录了mail.Body属性以确保其设置正确?当您说您可以将邮件重新发送给收到空白邮件的人而不会发出问题时,您是如何进行此操作的(即,您是记录最初使用的确切信息还是手动生成新邮件)?您是否正在验证
firstname
details
(即没有未转换的html字符)?就代码(即属性与字段)和典型值而言,
GlobalHelper.emailBody
看起来像什么?你是否曾经有人收到过一封空白电子邮件,并将其转发给你,以便你可以检查它?@DourHighArch-我相信我在创建HTML时验证了它,奇怪的是,它最近才成为一个问题-不过我会尝试一下。至少有两起投诉来自于拥有gmail和hotmail帐户的用户,所以我不会认为情况并非如此。杰森-我试着在邮件发送时登录。尸体是空的,从未被解雇过一次,尽管有人抱怨邮件是空白的。尽管我做了很多尝试,但还是无法重现问题。@Jerry是的,我检查了几封电子邮件,他们说邮件正文完全是空的,这是正确的。当我重新发送邮件时,我会呼叫完全相同的sub发送邮件,它会从与以前相同的位置加载参数@GJKH,多个线程可以同时调用GlobalHelper.emailBody吗?只需设置一个测试控制台应用程序,以相同的方式循环并向线程池添加一百万个这些项目,并在该循环中向线程池添加另外10个项目。我的笔记本电脑变热了,但一次也没用完。我检查了邮件正文是否为空,但一次也没有捕获到它。如果您暗示
MailMessage
对象无法传递到
QueueUserWorkItem
,则这是不正确的。实例成员不是线程安全的(在.Net framework类库中有一个常见警告),这意味着您不应该同时从多个线程访问同一个MailMessage对象。代码似乎无法做到这一点,因为每次调用
EmailConfirmation
都会实例化一个新的
MailMessage
对象,将其传递给
AddEmailToThreadPool
,然后再也无法访问它(可能的错误记录在一旁)。@DourHighArch我也在想同样的事情,但要使它成为一个问题
GlobalHelper.emailBody
必须是一个(并非微不足道的)属性,而不是一个普通字段。很高兴您似乎已经解决了您的问题。奇怪的是,如果它是由无效的html引起的,用户可以一次看到它,但不能再看到另一次。你知道用户是否使用了不同的电子邮件客户端、浏览器或计算机来查看这两条消息吗?可能,我认为可能是这样的,例如,他们没有显示在邮件客户端上,而是会显示在他们的手机上。但是,通过第三方与他们打交道使得提问/获得答案变得困难。我得到的唯一回应是“它正在工作”。公平地说,我并不完全相信问题已经解决,我不认为格式错误的文档类型会导致这种行为,我将拭目以待。