Option Strict On Imports System.Net.Http Public Class Form1 Private textBoxes As New List(Of TextBox)()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load textBoxes.AddRange({TextBox1, TextBox2, TextBox3, TextBox4, TextBox5, TextBox6}) End Sub
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Button1.Enabled = False
Dim queue As New List(Of Task)() For p = 0 To 5 Dim url = $"https://dobon.net/cgi-bin/vbbbs/cbbs.cgi?page={20 * (p - 1)}&H=F&no=0" Dim txt = textBoxes(p) Dim http As New HttpClient() queue.Add(http.GetStringAsync(url).ContinueWith( Sub(html) txt.Text = $"{url}{vbCrLf}{html.Result}", TaskScheduler.FromCurrentSynchronizationContext())) Next Await Task.WhenAll(queue)
ループ待機で「Loop Unitil 最後のページのイベント処理が完了した時」とするのではなく、 OpenReadCompleted イベントのハンドラーである onBinaryLoad にて、 If 最後のページのイベント処理が完了した時 Then '全て完了した時に動作させたい処理 End If のように実装するようにして、Button1 そのものは ループ待機せず、そのまま End Sub に向かって抜けてしまうようにします。
次のようなコードで自己解決しました。
お騒がせしてすみませんでした。
Private Sub onBinaryLoad(ByVal sender As Object, ByVal e As OpenReadCompletedEventArgs)
If Not (e.[Error] IsNot Nothing) OrElse (e.Cancelled) Then
DirectCast(Me.Controls.Find("TextBox" & e.UserState, True).First, TextBox).Text = New StreamReader(e.Result).ReadToEnd
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ServicePointManager.DefaultConnectionLimit = 8
Dim 変数Max As Integer = 16
Dim WcList As New List(Of WebClient)
For i = 1 To 変数Max
Dim TmpWc = New WebClient
WcList.Add(TmpWc)
AddHandler TmpWc.OpenReadCompleted, AddressOf onBinaryLoad
TmpWc.OpenReadAsync(New Uri("https:XXXX&page=" & i), i)
Next
Do
Application.DoEvents()
Loop Until WcList.All(Function(n) n.IsBusy = False)
End Sub
Webで複数のPageに分かれたデータをWebClientを使用してデータを取得して、それぞれのPage数と合致したTextBox.Nameに表示しようとしています。(今回は、階層的にtaxtBoxのControlが配置しているので、子も検索するコードになっています)I/O待ちが主体の処理なので、Parallelで回すのでは無く、WebClient.OpenReadAsyncで処理するのが最適と思い次のようなコードを書きました。
Public Class Form1
Private Sub onBinaryLoad(ByVal sender As Object, ByVal e As OpenReadCompletedEventArgs)
If Not (e.[Error] IsNot Nothing) OrElse (e.Cancelled) Then
DirectCast(Me.Controls.Find("TextBox" & e.UserState, True).First, TextBox).Text = New StreamReader(e.Result).ReadToEnd
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim 変数Max As Integer = 16
For i = 1 To 変数Max
Dim TmpWc = New WebClient
AddHandler TmpWc.OpenReadCompleted, AddressOf onBinaryLoad
TmpWc.OpenReadAsync(New Uri("https://XXXX&page=" & i), i)
Next
End Sub
End Class
提示したコードでは、Page数が16と限定していますが、実際は、不定です。
不定数となる全てのPageの読み込みが完了した判断は、どのように行えば宜しいのでしょうか?
詳しい方、いらっしゃいましたらご指南宜しくお願い致します。