VB.Net线程和Addhandler麻烦

时间:2016-07-20 03:43:14

标签: vb.net addhandler email-threading

再次问好StackOverflow社区!

我正在研究一个“SendLogfileClass”类。在这个课程中,我通过电子邮件将日志文件发送到所述电子邮件帐户那部分按预期工作。我遇到的问题是尝试处理异步完成事件。在上述事件期间,Addhandler将触发并在主窗体上设置StatusBar.StatusLabel。

以下是一些相关的代码块:

#Region "Imports"

    Imports System
    Imports System.Net
    Imports System.Net.Mail
    Imports System.Net.Mime
    Imports System.Threading
    Imports System.ComponentModel
    Imports System.IO

#End Region

Public Class Form1

#Region "Public"

    Private SendmailThread As Thread
    Private MailBody As String = Nothing

#End Region

#Region "Private"

    Private mailSent As Boolean = False

#End Region

    Public Function GetTimestamp() As String

        Dim t As Date = Date.Now
        Dim timestamp As String = Nothing

        Try

            timestamp = t.ToLongTimeString & " " & t.ToLongDateString

        Catch ex As Exception

            Return 1

        End Try

        Return timestamp

    End Function

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Try

            If LoggerClock.Enabled = True Then

                OutputConsole.Text = "logger Started: " & GetTimestamp() & vbNewLine
                OutputConsole.AppendText("Logfile Opened: " & GetTimestamp() & vbNewLine)

                StatusLabel.Text = "Logger Status: Active"
                StatusBar.Refresh()

            Else

                OutputConsole.Text = "logger Started: " & GetTimestamp() & vbNewLine

                StatusLabel.Text = "Logger Status: Inactive"
                StatusBar.Refresh()
            End If

            SendlogClock.Enabled = True

            ToggleViewForm(1)

        Catch ex As Exception

            Exit Sub

        End Try

    End Sub

    Public Function SetStatus(ByVal [status] As String) As Integer

        Try

            Thread.Sleep(1000)
            StatusLabel.Text = [status]
            StatusBar.Refresh()

        Catch ex As Exception

            Return 1

        End Try

        Return 0

    End Function

    Private Sub SendlogThreadTask()

        Try

            SendLogfile("user@gmail.com", "Logger Logfile", MailBody).ToString()

        Catch ex As Exception

            Exit Sub

        End Try

    End Sub

    Private Sub SendlogClock_Tick(sender As Object, e As EventArgs) Handles SendlogClock.Tick

        Try

            OutputConsole.AppendText("Logfile Closed: " & GetTimestamp() & vbNewLine)

            SendmailThread = New Thread(AddressOf SendlogThreadTask)
            SendmailThread.IsBackground = True
            SendmailThread.Start()

            OutputConsole.ResetText()
            OutputConsole.Text = "Logfile Opened: " & GetTimestamp() & vbNewLine

        Catch ex As Exception

            Exit Sub

        End Try

    End Sub

    Public Sub SendCompletedCallback(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)

        Try

            ' Get the unique identifier for this asynchronous operation.
            Dim token As String = CStr(e.UserState)

            If e.Cancelled Then

                StatusLabel.Text = "Send Canceled... " & token
                StatusBar.Refresh()

            End If

            If e.Error IsNot Nothing Then

                StatusLabel.Text = "Error: " & token & " " & e.Error.ToString() & " "
                StatusBar.Refresh()

            Else

                StatusLabel.Text = "Message Sent... "
                StatusBar.Refresh()

            End If

            mailSent = True

        Catch ex As Exception

            Exit Sub

        End Try

    End Sub

    Public Function SendLogfile(ByVal mailTo As String, ByVal mailSubject As String, ByVal mailBody As String, Optional ByVal doAttach As Boolean = False, Optional ByVal messageAttach As String = Nothing) As Integer

        Try

            ' SMTP Server
            Dim SmtpServer As String = "mail.domain.com"

            ' Command line argument must the the SMTP host.
            Dim Cli As New SmtpClient(SmtpServer)

            ' Specify the e-mail sender.
            ' Create a mailing address that includes a UTF8 character
            ' in the display name.
            Dim [from] As New MailAddress("logger@domain.com", "logger " & ChrW(&HD8) & " logs", System.Text.Encoding.UTF8)

            ' Set destinations for the e-mail message.
            Dim [to] As New MailAddress(mailTo)

            ' Specify the message content.
            Dim message As New MailMessage([from], [to])

            message.Body = mailBody

            ' Include some non-ASCII characters in body and subject.
            Dim someArrows As New String(New Char() {ChrW(&H2190), ChrW(&H2191), ChrW(&H2192), ChrW(&H2193)})

            message.Body += Environment.NewLine & someArrows
            message.BodyEncoding = System.Text.Encoding.UTF8
            message.Subject = mailSubject & someArrows
            message.SubjectEncoding = System.Text.Encoding.UTF8

            ' Put the mail attachment in a list of items
            'Dim attachment As New Attachment(messageAttach)

            ' Attach file.
            'If doAttach = True Then

            'If File.Exists(messageAttach) Then

            'message.Attachments.Add(attachment)

            'End If

            'End If

            ' Set the method that is called back when the send operation ends.
            AddHandler Cli.SendCompleted, AddressOf SendCompletedCallback

            ' The userState can be any object that allows your callback 
            ' method to identify this send operation.
            ' For this example, the userToken is a string constant.
            Dim userState As String = "OK"

            Cli.SendAsync(message, userState)

           'MsgBox("Sending message... press c to cancel mail. Press any other key to exit.")

            Dim answer As String = "OK" ' or CANCEL

            ' If the user canceled the send, and mail hasn't been sent yet,
            ' then cancel the pending operation.
            If answer.StartsWith("C") AndAlso mailSent = False Then

                Cli.SendAsyncCancel()

            End If

            ' Clean up.
            message.Dispose()

        Catch ex As Exception

            MsgBox("Encountered Error: " & vbNewLine & vbNewLine & ex.ToString())
            Return 1

        End Try

        Return 0

    End Function

End Class

1 个答案:

答案 0 :(得分:0)

您的事件处理程序在辅助线程上执行,在该事件处理程序中,您指的是MainForm的默认实例。默认实例是特定于线程的,因此它是与您在屏幕上查看的对象不同的表单对象。

您通常可以使用SynchronizationContext类来启用对UI线程的方法调用的编组,但在您的情况下这是不可能的,因为您实际上也是在辅助线程上创建对象。在这种情况下,您必须将对现有MainForm对象的引用传递给该邮件发件人,并使用它来使用其InvokeRequiredInvoke封送对UI线程的方法调用。 / BeginInvoke成员。