Ciao a tutti, sto provando a spulciare nel web per creare un downloader veramente asincrono. Tutti i codici o sample program che sto provando non sono completamente asincroni, e dunque, tutti freezano o meglio dire, non aggiornano il valore di una progress bar. O la aggiornano alla fine del download o nel caso di file di 20 o più mb, non si muove affatto!!
Sto provando ad usare la classe Progress <T> e la sua interfaccia IProgress<T>.
Il codice per scaricare funziona, ma vorrei implementare una progress bar funzionante e completamente asincrona, nel senso che anche se scaricassi un file prova di 1 giga, la progress bar resti efficiente e mostri il reale progresso del download.
Questo è il mio codice:
La classe d'aiuto:
Probabilmente scaricare da url ogni secondo non è il mio obbiettivo, ma avendo usato un codice non mio, proverò a rimuovere quella funzione successivamente.
Il mio obbiettivo per adesso è inserire una progressbar, e magari anche delle label con i bytes ricevuto e quelli totali da ricevere.
Grazie
Sto provando ad usare la classe Progress <T> e la sua interfaccia IProgress<T>.
Il codice per scaricare funziona, ma vorrei implementare una progress bar funzionante e completamente asincrona, nel senso che anche se scaricassi un file prova di 1 giga, la progress bar resti efficiente e mostri il reale progresso del download.
Questo è il mio codice:
Codice:
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
La classe d'aiuto:
Codice:
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
Probabilmente scaricare da url ogni secondo non è il mio obbiettivo, ma avendo usato un codice non mio, proverò a rimuovere quella funzione successivamente.
Il mio obbiettivo per adesso è inserire una progressbar, e magari anche delle label con i bytes ricevuto e quelli totali da ricevere.
Grazie