Как предотвратить отмену cancellationtoken во время загрузки строки
Я заполняю список из строки асинхронной загрузки с помощью httpclient.
Список немного изменен, так как мне нужно было событие прокрутки, и я нашел в интернете действительно классный класс для него.
Код класса Listbox:
Public Class BetterListBox Inherits ListBox ' Event declaration Public Delegate Sub BetterListBoxScrollDelegate(ByVal Sender As Object, ByVal e As BetterListBoxScrollArgs) Public Event Scroll As BetterListBoxScrollDelegate ' WM_VSCROLL message constants Private Const WM_VSCROLL As Integer = &H115 Private Const SB_THUMBTRACK As Integer = 5 Private Const SB_ENDSCROLL As Integer = 8 Protected Overrides Sub WndProc(ByRef m As Message) ' Trap the WM_VSCROLL message to generate the Scroll event MyBase.WndProc(m) If m.Msg = WM_VSCROLL Then Dim nfy As Integer = m.WParam.ToInt32() And &HFFFF If (nfy = SB_THUMBTRACK OrElse nfy = SB_ENDSCROLL) Then RaiseEvent Scroll(Me, New BetterListBoxScrollArgs(Me.TopIndex, nfy = SB_THUMBTRACK)) End If End If End Sub Public Class BetterListBoxScrollArgs ' Scroll event argument Private mTop As Integer Private mTracking As Boolean Public Sub New(ByVal top As Integer, ByVal tracking As Boolean) mTop = top mTracking = tracking End Sub Public ReadOnly Property Top() As Integer Get Return mTop End Get End Property Public ReadOnly Property Tracking() As Boolean Get Return mTracking End Get End Property End Class End Class
Я заполняю список с помощью:
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
И вспомогательный класс:
Imports System.Diagnostics Imports System.Net Imports System.Net.Http Imports System.Text.RegularExpressions Imports System.Threading 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
Что я уже пробовал:
Итак, я использую Await downloader.StopDownload() в listbox scroll event и mouse enter, а в listbox mouseleave eventI снова начинаю загрузку.
Проблема в том, что во время прокрутки я получаю сообщение об ошибке : System.ObjectDisposedException: "CancellationTokenSource был отменен". Я пытался использовать try catch напрасно , событие listbox mouseleave не запускает загрузку снова... У кого-нибудь есть идеи? Спасибо