Drarig29
Drarig29

Reputation: 2245

How to properly exit from canceled BackgroundWorker async?

I'm currently using this code, (which is working) but I'm not satisfied with how it looks... Is there a more professional way to do it ?

Here's the code I use now :

Private Sub BackgroundWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker.DoWork
    Try
        If BackgroundWorker.CancellationPending Then
            e.Cancel = True
            Exit Sub
        End If

        LatestVersion = Web.DownloadString(UpdateLink)

        If BackgroundWorker.CancellationPending Then
            e.Cancel = True
            Exit Sub
        End If

        If LatestVersion.Contains(InstalledVersion) Then
            e.Result = UP_TO_DATE
        Else
            e.Result = OUTDATED
        End If

        Web.Dispose()
    Catch ex As Exception
        e.Result = ex.Message
    End Try
End Sub

As you can see, I'm repeating two times the same condition. But imagine if there was more code, I should have repeat it more times...

My problem is that I would like to exit the Sub at anytime, as long as the BackgroundWorker.CancellationPending property is set to True.

I'm using the same condition two times because I wanna check if the operation has been canceled before, and after downloading of my string (I don't wanna wait for the string to be downloaded whereas I've already canceled the operation... it's a waste of time).

Should I use a While statement ? If yes, how ?

Upvotes: 1

Views: 159

Answers (2)

Drarig29
Drarig29

Reputation: 2245

I've found another solution. By the way, I've renamed Web by WebClient...

Here's my code :

Private Sub Form1_Load() Handles Form1.Load
    AddHandler WebClient.DownloadStringCompleted, AddressOf WebClient_DownloadStringCompleted
End Sub

Private Sub BackgroundWorker_DoWork() Handles BackgroundWorker.DoWork
    WebClient.DownloadStringAsync(New Uri(UpdateLink))
End Sub

Private Sub WebClient_DownloadStringCompleted(sender As Object, e As System.Net.DownloadStringCompletedEventArgs)
    Dim Output As String = Nothing

    If Not e.Cancelled Then
        LatestVersion = e.Result

        If LatestVersion.Contains(InstalledVersion) Then
            Output = UP_TO_DATE
        Else
            Output = OUTDATED
        End If
    End If
End Sub

And, to cancel the operation, I run WebClient.CancelAsync().

Upvotes: 0

usr
usr

Reputation: 171188

Don't use BackgroundWorker and this problem goes away. The code probably should be (mixture of VB and C#):

    //Instance field:
    CancellationTokenSource cts = ...;

    //Update method
    var downloadTask = HttpClient().DownloadString(UpdateLink, cts.Token);
    await Task.WhenAll(downloadTask, cts.Token); //Wait with timeout
    LatestVersion = await downloadTask;

    If LatestVersion.Contains(InstalledVersion) Then
        ShowResult(UP_TO_DATE);
    Else
        ShowResult(OUTDATED);
    End If

And if you want to cancel, signal cts.

Also, error handling is missing. This is easy to test for and add.

Upvotes: 2

Related Questions