VB.Net BackgroundWorker 和 AsyncCancel 无法正常工作

VB.Net BackgroundWorker and AsyncCancel Not Working Correctly

Whosebug 社区大家好!

我在使用 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("user@server.com", "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

一切正常。问题是您没有正确阅读它的工作原理。在 BackgroundWorker 上调用 CancelAsync(不是 AsyncCancel)不会取消任何内容。它所做的只是在 BackgroundWorker 对象上设置一个标志。您可以在 DoWork 事件处理程序中测试该标志,如果已设置,则由您停止工作。在您当前的代码中,直到发送电子邮件后才测试该标志,因此无论您是否尝试取消,当然都会发送电子邮件。

您高估了取消 BackgroundWorker 所能达到的效果。 BackgroundWorker 本身不知道您在 DoWork 事件处理程序中做什么,因此它不会简单地中止它。它使您有机会在代码中的适当位置终止任务。如果没有合适的点则无法取消。

在您的情况下,一旦您在 SmtpClient 上调用 Send,在同步方法 returns 之前您无法执行任何操作,因此您无法取消它。您应该做的是根本不使用 BackgroundWorker,而是 SmtpClient class 中内置的异步功能。它有一个 SendAsync 方法和一个 SendAsyncCancel 方法,所以你可以让它为你处理多线程。