Home > Blockchain >  Cancel Task.Run job
Cancel Task.Run job

Time:04-28

I have async method as shown below. I would like to have possibility to cancel it when user decide to stop the job. How could i do that in new button CancelUpdate_Click

    Private Async Sub btnUpdate_Click(sender As Object, e As EventArgs) Handles btnUpdate.Click
            Await DoWorkAsync()
    End Sub
    
    Private Function DoWorkAsync() As Task(Of List(Of Vals))
                Return _
                    Task.Run(
                        Async Function() _
                                _migrator.PrepareMigration(CInt(Invoke(New Func(Of Integer)(Function() lbNumms.SelectedValue))), CInt(Invoke(New Func(Of Integer)(Function() lbPro.SelectedValue)))))
    End Function
    
Private Sub CancelUpdate_Click(sender As Object, e As EventArgs) Handles CancelUpdate.Click
            'Stop DoWorkAsync if running
    End Sub

UPDATED:

Private _tokenSource As New CancellationTokenSource()
        Private ReadOnly _token = _tokenSource.Token

Private Async Sub btnUpdate_Click(sender As Object, e As EventArgs) Handles btnUpdate.Click
     Try
        Private ReadOnly _tokenSource As New CancellationTokenSource()
    Private ReadOnly _token = _tokenSource.Token
            Await DoWorkAsync()
        Catch oe As OperationCanceledException
                MessageBox.Show("Task has been cancelled")
      Finally
        _tokenSource.Dispose()
      End Try
    End Sub
        
        Private Function DoWorkAsync() As Task(Of List(Of Vals))
                    Return _
                        Task.Run(
                            Function()
                                Dim tokenSource = New CancellationTokenSource()
                                Dim token = tokenSource.Token
                                Return _migrator.PrepareMigration(CInt(Invoke(New Func(Of Integer)(Function() lbNumms.SelectedValue))), CInt(Invoke(New Func(Of Integer)(Function() lbProducent.SelectedValue))), _token)
                            End Function)
        End Function
            
        
        Public Function PrepareMigration(value1 As Integer, value2 As Integer, cancellationToken As CancellationToken) As List(Of Vals))
        
        cancellationToken.ThrowIfCancellationRequested() 
        MethodA()
        cancellationToken.ThrowIfCancellationRequested()
        MethodB()
        
        End Function
        
        Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
                      _tokenSource.Cancel()
        End Sub

CodePudding user response:

Cancellation isn't something that just magically works. It has to be explicitly coded. In this case, your PrepareMigration routine needs to take a CancellationToken parameter and needs to periodically check to see if that parameter's IsCancellationRequested property has been set to True.

One shortcut for doing this is to periodically call ThrowIfCancellationRequested on the token; this will result in an OperationCanceledException if the property is set.

If you are working in a routine that returns a Task, you can return Task.FromCanceled.

You would get the CancellationToken to pass in from a CancellationTokenSource. Then the event handler for the cancel button would call Cancel on the source to signal the issued token.

For example, if you have processing that involves multiple steps, maybe it would work like this:

'Include other parameters as appropriate.
Sub PrepareMigration(ByVal token As CancellationToken)
    DoStep1()

    token.ThrowIfCancellationRequested()
    DoStep2()

    '...

    token.ThrowIfCancellationRequested()
    DoStepn()
End Sub

Or, if you have something where you are processing a set of items, maybe it would look like this:

Sub PrepareMigration(ByVal token As CancellationToken)
    For Each item In itemsToProcess
        token.ThrowIfCancellationRequested()
        DoTheItem(item)
    Next
End Sub

Mix and match as required. If a routine called in a particular step is especially long-running, that routine itself might need to be cancellation-aware.

Ultimately, where you put checks depends on the details of the steps of your calculation (including potentially "quick" vs "slow" steps) and what limits you want to set on how long a user has to wait until a requested cancellation takes effect.

  • Related