-
Oct 12th, 2020, 07:00 PM
#1
Thread Starter
Lively Member
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.
-
Oct 13th, 2020, 07:28 AM
#2
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.
-
Oct 13th, 2020, 08:47 AM
#3
Thread Starter
Lively Member
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
-
Oct 14th, 2020, 07:36 AM
#4
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|