2016-07-25 3 views
0

Здравствуйте, снова Сообщество StackOverflow!VB.Net BackgroundWorker и AsyncCancel не работают правильно

У меня возникли проблемы с BackgroundWorker и AsyncCancel. BackgroundWorker просто отправляет электронное письмо, но я хотел бы иметь возможность сообщить, когда отправлено задание или письмо, а также можно отменить отправку задачи или электронной почты.

Проблема заключается в том, что после нажатия на отмену она продолжается, а затем сообщает об ошибке, а не отменяется.

Любая помощь очень ценится!

Спасибо!

Вот мои полные комментарии код минус и импорт:

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

    StatusLabel.Text &= "Idle" 

End Sub 

Private Sub SendmailBackgroundWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles SendmailBackgroundWorker.DoWork 

    Try 

     Dim Smtp As New SmtpClient() 
     Dim Email As New MailMessage() 

     Smtp.Port = 25 
     Smtp.Host = "mail.server.com" 

     Smtp.EnableSsl = False 
     Smtp.UseDefaultCredentials = False 

     Smtp.Credentials = New Net.NetworkCredential("[email protected]", "password") 

     Email = New MailMessage() 
     Email.From = New MailAddress(FromTextBox.Text) 
     Email.To.Add(ToTextBox.Text) 
     Email.Subject = SubjectTextBox.Text 
     Email.IsBodyHtml = False 
     Email.Body = BodyTextBox.Text 

     Smtp.Send(Email) 

    Catch ex As Exception 

     MsgBox("Sendmail Error!" & vbNewLine & vbNewLine & ex.ToString) 

    End Try 

    If SendmailBackgroundWorker.CancellationPending Then 

     StatusLabel.Text = "Canceling" 
     e.Cancel = True 

    End If 

End Sub 

Private Sub SendmailBackgroundWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles SendmailBackgroundWorker.RunWorkerCompleted 

    StatusLabel.Text = "Status: " 

    If (e.Error IsNot Nothing) Then 


     StatusLabel.Text &= "Worker Error!" & vbNewLine & vbNewLine & e.Error.Message 

    ElseIf e.Cancelled Then 

     StatusLabel.Text &= "Canceled!" 

    Else 

     StatusLabel.Text &= "Sent!" 

    End If 

    SendButton.Enabled = True 
    CancelButton.Enabled = False 

End Sub 

Private Sub SendButton_Click(sender As Object, e As EventArgs) Handles SendButton.Click 

    StatusLabel.Text = "Status: " 

    SendButton.Enabled = False 
    CancelButton.Enabled = True 

    SendmailBackgroundWorker.WorkerSupportsCancellation = True 
    SendmailBackgroundWorker.WorkerReportsProgress = True 

    StatusLabel.Text &= "Sending..." 

    SendmailBackgroundWorker.RunWorkerAsync() 

End Sub 

Private Sub CancelButton_Click(sender As Object, e As EventArgs) Handles CancelButton.Click 

    CancelButton.Enabled = False 
    SendmailBackgroundWorker.CancelAsync() 

End Sub 
+0

Другой вопрос, который у вас есть, заключается в том, что отправка почты может быть очень быстрой. Возможно, пользователь даже не успел отменить отправку. – Enigmativity

ответ

1

Это работает точно так, как это должно быть. Проблема в том, что вы не правильно прочитали, как это работает. Вызов CancelAsync (НЕ AsyncCancel) на BackgroundWorker НЕ отменяет ничего. Все, что он делает, устанавливается на объекте BackgroundWorker. Вам решать проверить этот флаг в вашем обработчике событий DoWork, и, если он установлен, вам нужно прекратить работу. В вашем текущем коде вы не проверяете этот флаг до тех пор, пока сообщение не будет отправлено, поэтому, конечно, письмо отправляется независимо от того, пытаетесь ли вы отменить или нет.

Вы преувеличиваете то, что может сделать BackgroundWorker. Сам BackgroundWorker не знает, что вы делаете в обработчике событий DoWork, поэтому он не собирается просто прервать его. Это дает вам возможность прекратить выполнение задачи в соответствующей точке кода. Если нет подходящей точки, вы ничего не можете отменить.

В вашем случае, как только вы вызываете Send на свой SmtpClient, вы ничего не можете сделать до тех пор, пока этот синхронный метод не вернется, поэтому вы не можете его отменить. То, что вы должны делать, - это не использование BackgroundWorker, а скорее асинхронная функциональность, встроенная в класс SmtpClient. Он имеет метод SendAsync и метод SendAsyncCancel, поэтому вы можете позволить ему обрабатывать многопоточность для вас.

+0

Спасибо за помощь Enigmativity и jmcilhinney, я буду изучать это утром. –

Смежные вопросы