2016-07-20 57 views
0

你好再次StackOverflow社区!VB.Net线程和Addhandler问题

我正在研究“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("[email protected]", "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("[email protected]", "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 
+0

我加入了同一个应用程序的简化的单级版本,请你给我如何完成所需任务的例子吗? –

回答

0

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

您通常可以使用SynchronizationContext类来启用将方法调用编组到UI线程,但在您的情况下这是不可能的,因为您实际上是在辅助线程上创建对象。在这种情况下,你必须通过一个参照现有MainForm对象到该邮件发送者和使用利用其InvokeRequiredInvoke/BeginInvoke成员编组方法调用到UI线程。