-
Sep 24th, 2020, 03:49 PM
#1
Thread Starter
Lively Member
[vb.net] How to use a progress bar while downloading through HttpClient
Hi everybody,
I want to use an async progress bar that show the download progress. I'm trying to do it using Progress <T> class.
I've been trying a lots of codes but none of them is really async and the progress bar is really never being updated during download.
My code is:
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)
Private Async Sub btnStopDownload_Click(sender As Object, e As EventArgs) Handles btnStopDownload.Click
Await downloader.StopDownload()
End Sub
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 pattern As String = "<(?:[^>=]|='[^']*'|=""[^""]*""|=[^'""][^\s>]*)*>"
Dim downloadTimeWatch As Stopwatch = New Stopwatch()
downloadTimeWatch.Start()
Do
If cts.IsCancellationRequested Then Return
Try
Dim response = Await client.GetAsync(url, HttpCompletionOption.ResponseContentRead, token)
Dim data = Await response.Content.ReadAsStringAsync()
data = WebUtility.HtmlDecode(Regex.Replace(data, pattern, ""))
progress.Report(data)
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
Any idea? Thanks
-
Sep 25th, 2020, 08:36 AM
#2
Re: [vb.net] How to use a progress bar while downloading through HttpClient
Simply declarate the method StarDownLoad with async and the Task needs await. Here is a simple example, does no downloading. The form remains responsive.
Two buttons, one ProgressBar.
Code:
Imports System.Threading
''' <summary>
''' Simple example for IProgress show progress with ProgressBar.
''' Note the method AsyncMethod should really be in a class that
''' has an event which the form subscribes too for updating the
''' ProgressBar.
''' </summary>
Public Class ProgressForm
Private _cts As New CancellationTokenSource()
Private Sub ReportProgress(value As Integer)
ProgressBar1.Value = value
End Sub
Private Async Function AsyncMethod(progress As IProgress(Of Integer), ct As CancellationToken) As Task
For index As Integer = 0 To 100
Await Task.Delay(1)
If ct.IsCancellationRequested Then
ct.ThrowIfCancellationRequested()
End If
If progress IsNot Nothing Then
progress.Report(index)
End If
Next
End Function
Private Async Sub StartButton_Click(sender As Object, e As EventArgs) _
Handles StartButton.Click
ProgressBar1.Value = 0
Await Task.Delay(1)
Dim cancelled = False
If _cts.IsCancellationRequested = True Then
_cts.Dispose()
_cts = New CancellationTokenSource()
End If
Dim progressIndicator = New Progress(Of Integer)(AddressOf ReportProgress)
Try
Await AsyncMethod(progressIndicator, _cts.Token)
Catch ex As OperationCanceledException
cancelled = True
End Try
If cancelled Then
Await Task.Delay(1000)
End If
End Sub
Private Sub CancelButton_Click(sender As Object, e As EventArgs) _
Handles CancelButton.Click
_cts.Cancel()
End Sub
End Class
-
Sep 25th, 2020, 09:43 AM
#3
Thread Starter
Lively Member
Re: [vb.net] How to use a progress bar while downloading through HttpClient
Originally Posted by kareninstructor
Simply declarate the method StarDownLoad with async and the Task needs await. Here is a simple example, does no downloading. The form remains responsive.
Two buttons, one ProgressBar.
Code:
Imports System.Threading
''' <summary>
''' Simple example for IProgress show progress with ProgressBar.
''' Note the method AsyncMethod should really be in a class that
''' has an event which the form subscribes too for updating the
''' ProgressBar.
''' </summary>
Public Class ProgressForm
Private _cts As New CancellationTokenSource()
Private Sub ReportProgress(value As Integer)
ProgressBar1.Value = value
End Sub
Private Async Function AsyncMethod(progress As IProgress(Of Integer), ct As CancellationToken) As Task
For index As Integer = 0 To 100
Await Task.Delay(1)
If ct.IsCancellationRequested Then
ct.ThrowIfCancellationRequested()
End If
If progress IsNot Nothing Then
progress.Report(index)
End If
Next
End Function
Private Async Sub StartButton_Click(sender As Object, e As EventArgs) _
Handles StartButton.Click
ProgressBar1.Value = 0
Await Task.Delay(1)
Dim cancelled = False
If _cts.IsCancellationRequested = True Then
_cts.Dispose()
_cts = New CancellationTokenSource()
End If
Dim progressIndicator = New Progress(Of Integer)(AddressOf ReportProgress)
Try
Await AsyncMethod(progressIndicator, _cts.Token)
Catch ex As OperationCanceledException
cancelled = True
End Try
If cancelled Then
Await Task.Delay(1000)
End If
End Sub
Private Sub CancelButton_Click(sender As Object, e As EventArgs) _
Handles CancelButton.Click
_cts.Cancel()
End Sub
End Class
Hi Karen thanks for your reply. I'd like to know where and how I should insert a Download in your code. My problem is that I know how to download, I just don't know how to make it work completely with your code/mine or viceversa.
I assume It won't be enough just to create a webclient and make a download async, How can I "connect" the download with your async example code?
Thanks
-
Sep 27th, 2020, 09:42 PM
#4
Re: [vb.net] How to use a progress bar while downloading through HttpClient
Look at the code. It contains this call:
vb.net Code:
Await AsyncMethod(progressIndicator, _cts.Token)
to this method:
vb.net Code:
Private Async Function AsyncMethod(progress As IProgress(Of Integer), ct As CancellationToken) As Task
So the example shows you how to make a call to an asynchronous method that takes IProgress(Of Integer) and CancellationToken objects as arguments and display progress from that method. Do you have any asynchronous methods in your code that take arguments of those types that you might want to call and display progress from?
-
Sep 29th, 2020, 12:49 AM
#5
Banned
Re: [vb.net] How to use a progress bar while downloading through HttpClient
Originally Posted by kareninstructor
Simply declarate the method StarDownLoad with async and the Task needs await. Here is a simple example, does no downloading. The form remains responsive.
Two buttons, one ProgressBar.
Code:
Imports System.Threading
''' <summary>
''' Simple example for IProgress show progress with ProgressBar.
''' Note the method AsyncMethod should really be in a class that
''' has an event which the form subscribes too for updating the
''' ProgressBar.
''' </summary>
Public Class ProgressForm
Private _cts As New CancellationTokenSource()
Private Sub ReportProgress(value As Integer)
ProgressBar1.Value = value
End Sub
Private Async Function AsyncMethod(progress As IProgress(Of Integer), ct As CancellationToken) As Task
For index As Integer = 0 To 100
Await Task.Delay(1)
If ct.IsCancellationRequested Then
ct.ThrowIfCancellationRequested()
End If
If progress IsNot Nothing Then
progress.Report(index)
End If
Next
End Function
Private Async Sub StartButton_Click(sender As Object, e As EventArgs) _
Handles StartButton.Click
ProgressBar1.Value = 0
Await Task.Delay(1)
Dim cancelled = False
If _cts.IsCancellationRequested = True Then
_cts.Dispose()
_cts = New CancellationTokenSource()
End If
Dim progressIndicator = New Progress(Of Integer)(AddressOf ReportProgress)
Try
Await AsyncMethod(progressIndicator, _cts.Token)
Catch ex As OperationCanceledException
cancelled = True
End Try
If cancelled Then
Await Task.Delay(1000)
End If
End Sub
Private Sub CancelButton_Click(sender As Object, e As EventArgs) _
Handles CancelButton.Click
_cts.Cancel()
End Sub
End Class
karen you look good,i like you
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
|