Results 1 to 4 of 4

Thread: How to prevent CancellationToken from being cancelled during downloadstring

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Jul 2013
    Posts
    108

    How to prevent CancellationToken from being cancelled during downloadstring

    Hi everybody, I'm populating a listbox from an async download string using httpclient.
    The listbox is slightly modified as I needed a scroll event and i found online a really cool class for it.
    So I'm using the same code as here: https://stackoverflow.com/questions/...01853#64001853

    Code:
    Private downloader As MyDownloader = Nothing
    
    Private Sub btnStartDownload_Click(sender As Object, e As EventArgs) Handles btnStartDownload.Click
        Dim progress = New Progress(Of String)(
            Sub(data)
                ' We're on the UI Thread here
                ListBox1.Items.Clear()
                ListBox1.Items.AddRange(Split(data, vbLf))
                RichTextBox1.SelectionStart = RichTextBox1.TextLength
            End Sub)
    
        Dim url As Uri = New Uri("https://SomeAddress.com")
        downloader = New MyDownloader()
        ' Download from url every 1 second and report back to the progress delegate
        downloader.StartDownload(progress, url, 1)
    And the helper class:
    Code:
    Imports System.Diagnostics
    Imports System.Net
    Imports System.Net.Http
    Imports System.Text.RegularExpressions
    
    Public Class MyDownloader
        Private Shared ReadOnly client As New HttpClient()
        Private ReadOnly cts As CancellationTokenSource = New CancellationTokenSource()
        Private interval As Integer = 0
    
        Public Sub StartDownload(progress As IProgress(Of String), url As Uri, intervalSeconds As Integer)
            interval = intervalSeconds * 1000
            Task.Run(Function() DownloadAsync(progress, url, cts.Token))
        End Sub
    
        Private Async Function DownloadAsync(progress As IProgress(Of String), url As Uri, token As CancellationToken) As Task
            Dim responseData As String = String.Empty
            Dim pattern As String = "<(?:[^>=]|='[^']*'|=""[^""]*""|=[^'""][^\s>]*)*>"
            Dim downloadTimeWatch As Stopwatch = New Stopwatch()
            downloadTimeWatch.Start()
            Do
                If cts.IsCancellationRequested Then Return
                Try
                    Using response = Await client.GetAsync(url, HttpCompletionOption.ResponseContentRead, token)
                        responseData = Await response.Content.ReadAsStringAsync()
                        responseData = WebUtility.HtmlDecode(Regex.Replace(responseData, pattern, ""))
                    End Using
                    progress.Report(responseData)
    
                    Dim delay = interval - CInt(downloadTimeWatch.ElapsedMilliseconds)
                    Await Task.Delay(If(delay <= 0, 10, delay), token)
                    downloadTimeWatch.Restart()
                Catch tcEx As TaskCanceledException
                    ' Don't care - catch a cancellation request
                    Debug.Print(tcEx.Message)
                Catch wEx As WebException
                    ' Internet connection failed? Internal server error? See what to do
                    Debug.Print(wEx.Message)
                End Try
            Loop
        End Function
    
        Public Async Function StopDownload() As Task
            Try
                cts.Cancel()
                client?.CancelPendingRequests()
                Await Task.Delay(interval)
            Finally
                client?.Dispose()
                cts?.Dispose()
            End Try
        End Function
    End Class
    So instead of using a button to stop the timer, I am using the listbox scroll event:
    Code:
    Await downloader.StopDownload()
    but this seems not working as i get the following error:
    System.ObjectDisposedException: 'CancellationTokenSource has been cancelled.
    The same error also when I'm using the same code in listbox mouse enter event..
    I wanted to stop the timer when the mouse enter the listbox and start again when the mouse leave it.
    Does anyone have any idea about how to solve it?
    In the simple buttons is working perfectly.
    Thanks
    Last edited by matty95srk; Oct 13th, 2020 at 06:16 AM.

  2. #2
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,684

    Re: How to prevent CancellationToken from being cancelled during downloadstring

    Hello,

    but this seems not working as i get the following error:
    System.ObjectDisposedException: 'CancellationTokenSource has been cancelled.
    The same error also when I'm using the same code in listbox mouse enter event..
    This happens because ThrowIfCancellationRequested throws an exception which you are not checking for which can be done by wrapping the caller code in a try/catch.

    Check out the following code sample to see how to properly check for cancellation.

    Also the CancellationTokenSource belong not in the class doing the work but instead in the class/form calling the worker class and check each time the operation starts to see if the CancellationTokenSource has been used already as shown in the code sample mentioned above.

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Jul 2013
    Posts
    108

    Re: How to prevent CancellationToken from being cancelled during downloadstring

    Hello Kareninstructor,
    Could you explain where I am calling ThrowIfCancellationRequested?

    Also, In you code sample I can just see this code, Am I right?
    https://github.com/karenpayneoregon/...ress3/Form1.vb

    if yes, then Is the following code missing in my code?
    Also the CancellationTokenSource belong not in the class doing the work but instead in the class/form calling the worker class and check each time the operation starts to see if the CancellationTokenSource has been used already as shown in the code sample mentioned above.
    Code:
     ' Reset if needed, if was ran and cancelled before
            '
            If _cts.IsCancellationRequested = True Then
                _cts.Dispose()
                _cts = New CancellationTokenSource()
            End If

    Also I can't see you using any class in your code right? Which is making me really confused on this.. Could you please explain me with a code answer? Thanks
    Mattia

  4. #4
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,684

    Re: How to prevent CancellationToken from being cancelled during downloadstring

    First off, here the class where the class is created here.

    If you remove

    Code:
    If _cts.IsCancellationRequested = True Then
        _cts.Dispose()
        _cts = New CancellationTokenSource()
    End If
    And click the start button not having

    If _cts.IsCancellationRequested = True Then

    and cancel was invoked, we are still in a cancel state and the process never runs past

    Code:
    If ct.IsCancellationRequested Then
        ct.ThrowIfCancellationRequested()
    End If
    Here is what I see when you ask these question, you have not analyzed/studied the code which needs to be done if you are going to use the code presented.

    Attachment 179007

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width