Async
とTasks
を使用して複数のURLのデータをダウンロードするMicrosoftのexampleを使用しています。asyncを使用してウェブページコンテンツを並行してダウンロードする
私の要件は200分のリンクを200分ダウンロードして2分後に同じ200個のURLのセットが再びダウンロードされるようにすることです。私は、大部分がネットワーク速度に依存し、CPUの電力にはあまり依存しないことを認識しています。これはIOバインドプロセスではないためです。
ネットワークとCPUがこの操作をサポートしており、ボトルネックにはならないと仮定すると、実際にはタスクのタイムアウト後にタイムアウトとキャンセルの例外が発生しています。
質問は同じですが、これを長時間実行するタスクに変更して、タスクがタイムアウトしないようにすることはできますか?私はTaskCreationOptions
列挙型の使用を認識しており、LongRunning
を使用しています。ただし、問題は次のとおりです。 1)以下の例のタスクを作成するときにこのパラメータを指定する方法と、リンクを指定する方法はありますか? 2)定義LongRunning
とは何ですか?これは、各タスクがもうタイムアウトしないことを意味しますか? 3)明示的に無限タイムアウトを他の何らかの方法で設定することはできますか?
基本的には、特定のURLのダウンロードプロセスが完了すると、同じURLのダウンロードが再開されます。つまり、同じURLが繰り返しダウンロードされるため、タスクは決して行われません(MSDNの例のURLは、私が起動するURLではなく、1分ごとに内容が変化する他のURLがあるため、毎分少なくとも1回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スティーブン。私は 'ServicePointManager.DefaultConnectionLimit'がやったと思う。もちろん、私は 'HttpClient.Timeout'を設定しましたが、それがあってもなくても、何の違いも気付かなかったのです。しかし、私は今ストリームを読んでいるランダムなエラーを取得しています。私の推測は、ストリームの要求と読んだ時間の間に閉鎖されているストリームのためです。そのような状況では、私の要件は、しかし、その後、 'HttpClient'オブジェクトはタイムアウトになります。どのようにすれば、タイムアウトすることなく再試行できるようにコードを構造化するべきですか? – Kallol
' Task.Delay'を待ち、 'Get *'を再呼び出しできます。私は、プロダクション品質の再試行のためにPollyのようなライブラリを使うことをお勧めします。 –