我使用的是Microsoft的example,它使用Async
和Tasks
下载多个URL的数据。使用异步并行下载网页内容
我的要求是在1分钟内完成200个链接的下载,以便第二分钟时,同一组200个URL将再次开始下载。我知道很大程度上取决于网络速度和CPU功率,因为这不是一个IO绑定的过程。
假设网络和CPU会支持这个操作并且不会成为一个瓶颈,实际上我会在一段时间后看到超时和取消异常。
因此,问题是在同一个例子中,我可以将其更改为长时间运行的任务,以便任务不超时?我知道使用TaskCreationOptions
枚举并使用LongRunning
。但是,问题是: 1)在下面的示例中创建任务并提供链接时,如何提供此参数? 2)什么是定义LongRunning
?这是否意味着每个任务不会超时? 3)我可以通过其他的意思明确地设置无限超时吗?
基本上,我的要求是,如果一个特定的URL的下载过程完成,它将再次触发下载相同的URL - 这意味着同一个URL将被一遍又一遍地下载,因此任务不应该完整(MSDN示例中的URL不是我将触发的URL,将会有其他URL,其内容每分钟都会更改,因此我需要不断每分钟至少下载一次该URL)。
从上面的例子链接粘贴在这里的代码太:
Dim cts As CancellationTokenSource
Dim countProcessed As Integer
Private Async Sub startButton_Click(sender As Object, e As RoutedEventArgs)
' Instantiate the CancellationTokenSource.
cts = New CancellationTokenSource()
resultsTextBox.Clear()
Try
Await AccessTheWebAsync(cts.Token)
resultsTextBox.Text &= vbCrLf & "Downloads complete."
Catch ex As OperationCanceledException
resultsTextBox.Text &= vbCrLf & "Downloads canceled." & vbCrLf
Catch ex As Exception
resultsTextBox.Text &= vbCrLf & "Downloads failed." & vbCrLf
End Try
' Set the CancellationTokenSource to Nothing when the download is complete.
cts = Nothing
End Sub
Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
If cts IsNot Nothing Then
cts.Cancel()
End If
End Sub
Async Function AccessTheWebAsync(ct As CancellationToken) As Task
Dim client As HttpClient = New HttpClient()
' Call SetUpURLList to make a list of web addresses.
Dim urlList As List(Of String) = SetUpURLList()
' ***Create a query that, when executed, returns a collection of tasks.
Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
From url In urlList Select ProcessURLAsync(url, client, ct)
' ***Use ToList to execute the query and start the download tasks.
Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()
Await Task.WhenAll(downloadTasks)
'Ideally, this line should never be reached
Console.WriteLine("Done")
End Function
Async Function ProcessURLAsync(url As String, client As HttpClient, ct As CancellationToken) As Task(Of Integer)
Console.WriteLine("URL=" & url)
' GetAsync returns a Task(Of HttpResponseMessage).
Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)
' Retrieve the web site contents from the HttpResponseMessage.
Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()
Interlocked.Increment(countProcessed)
Console.WriteLine(countProcessed)
Return urlContents.Length
End Function
Private Function SetUpURLList() As List(Of String)
Dim urls = New List(Of String) From
{
"http://msdn.microsoft.com",
"http://msdn.microsoft.com/en-us/library/hh290138.aspx",
"http://msdn.microsoft.com/en-us/library/hh290140.aspx",
"http://msdn.microsoft.com/en-us/library/dd470362.aspx",
"http://msdn.microsoft.com/en-us/library/aa578028.aspx",
"http://msdn.microsoft.com/en-us/library/ms404677.aspx",
"http://msdn.microsoft.com/en-us/library/ff730837.aspx",
"http://msdn.microsoft.com/en-us/library/hh290138.aspx",
"http://msdn.microsoft.com/en-us/library/hh290140.aspx"
'For space constraint I am not including the 200 URLs, but pls assume the above list contains 200 URLs
}
Return urls
End Function
Thx Stephen。我认为'ServicePointManager.DefaultConnectionLimit'完成了这个诀窍。当然,我也设置了'HttpClient.Timeout',但没有注意到它有没有区别。但我现在正在得到随机错误阅读流“。我的猜测是因为连接到流在请求和读取之间关闭,在这种情况下,我的要求是等待,比如说20秒,然后重试那么'HttpClient'对象会超时,任何建议我应该如何构造代码,以便我可以在没有超时的情况下重试? – Kallol
您可以'等待Task.Delay',然后重新调用'Get *'。我建议使用像波莉这样的库进行生产质量重试。 –