0

我使用的是Microsoft的example,它使用AsyncTasks下载多个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 

回答

2

问题,因此,在相同的例子,我可以将其更改为长时间运行的任务,这样的任务不会超时?

任务本身不超时。你可能看到的是HTTP请求超时。长时间运行的任务没有任何不同的超时语义。

我知道使用TaskCreationOptions枚举和使用LongRunning。

你也应该知道,他们应该几乎从不使用。


您可能会因为您的所有请求触及同一网站而超时。尝试将ServicePointManager.DefaultConnectionLimit设置为int.MaxValue,并且可能还会增加HttpClient.Timeout

+0

Thx Stephen。我认为'ServicePointManager.DefaultConnectionLimit'完成了这个诀窍。当然,我也设置了'HttpClient.Timeout',但没有注意到它有没有区别。但我现在正在得到随机错误阅读流“。我的猜测是因为连接到流在请求和读取之间关闭,在这种情况下,我的要求是等待,比如说20秒,然后重试那么'HttpClient'对象会超时,任何建议我应该如何构造代码,以便我可以在没有超时的情况下重试? – Kallol

+0

您可以'等待Task.Delay',然后重新调用'Get *'。我建议使用像波莉这样的库进行生产质量重试。 –