現在、WGETを使用して複数のcsvファイルを異なるサーバーからダウンロードするプログラムをコーディングしています。 WaitForExit(10000)メソッドを使用するプロセスとしてWGETを呼び出すため、すべてのダウンロードは新しいスレッドです.WGETはダウンロードする時間が10秒です。その時間内にダウンロードが完了しなかった場合、サーバーは時間内に応答しなかったため、スレッドは強制終了されます。GUI上のアクションのマルチスレッドの順序
また、私のプログラムが現在行っていることと、どのスレッドがどのステータスで終了したのかを記録するリストビューがあります。
だから(lvw_logが私のリストビューで)ログに記録する私の方法です:
Public Delegate Sub LogDelegate(ByVal Text As String)
Public Sub Log(Text As String)
If lvw_Log.InvokeRequired Then
lvw_Log.BeginInvoke(New LogDelegate(AddressOf Log), New Object() {Text})
Else
lvw_Log.Items.Add(DateTime.Now + ": " + Text)
lvw_Log.TopIndex = lvw_Log.Items.Count - 1
lvw_Log.Refresh()
End If
End Sub
テキストがWGET-スレッドの1から私のListViewに追加する必要がある場合、デリゲートが呼び出されます。 'p'は、スレッドにアクセス可能な変数のセットを渡すための、自分のクラスのオブジェクトです。
私はWGETThreadArrayと呼ばれるのArrayList内のすべてのスレッドを格納します。
Dim WGETThreadArray As New ArrayList
For i = 0 to NumberOfFilesToDownload - 1
Dim WGETThread As New System.Threading.Thread(AddressOf StartWGET)
WGETThreadArray.Add(WGETThread)
Log("Starting thread " + i.ToString)
WGETThreadArray(i).Start(p)
Next
今、私はすべてのスレッドが終了するか、中止されるのを待つしたい:
Log("Waiting for threads to finish")
For i = 0 To WGETThreadArray.Count - 1
WGETThreadArray(i).Join()
Next
Log("All threads closed")
Log("Downloaded all DB-Info-Files")
スレッド(メソッドStartWGET)されますこれは:
Public Sub StartWGET(p As Object)
'this method is called for each thread to parallely download the necessary files
Dim procInfo As New ProcessStartInfo(p.PathToWgetExe, p.ArgumentString)
procInfo.CreateNoWindow = False
procInfo.UseShellExecute = True
Dim WGETProcessHandler As System.Diagnostics.Process = System.Diagnostics.Process.Start(procInfo)
If Not WGETProcessHandler.WaitForExit(10000) Then 'if WGET doesn't finish within '10000' milliseconds, the thread gets killed
WGETProcessHandler.Kill()
Log("DB " + p.DBName + " was not loaded. Thread " + p.ThreadIndex.ToString + " killed ")
DatabaseArray(p.ThreadIndex).isLoaded = False
WGETThreadArray(p.ThreadIndex).Abort()
Else
DatabaseArray(p.ThreadIndex).isLoaded = True
Log(p.URL + " downloaded. Thread " + p.ThreadIndex.ToString + " ended successfully.")
End If
End Function
ご覧のとおり、「ログ」メソッドがスレッド内で呼び出されます。問題は、メインスレッドは常に他のスレッドの前にListViewに書き込むことです。だから私は、 "スレッドが正常に終了しました"のようなメッセージの前に "すべてのスレッドが閉じられました"という行を見る。私はforループで.Join()メソッドを使っていましたが。すべてのスレッドが終了するまで待ちます。
他のすべてのWGETスレッドが完了するまでメインスレッドを一時停止させるにはどうすればよいですか。また、メインスレッドが引き継ぎ、すべてのスレッドが終了したことを知らせる前に、どうすればそれらをログに記録できますか?
私は説明するのが難しいことを知っており、私は自分自身を明確にしたいと思っています。そうでない場合は、私にもう一度聞いてください。
スレッドの代わりにスレッドを使用する特別な理由はありますか?処理が簡単なタスク? –
私はスレッドを使用しました。なぜなら私は正直であると分かっていなかったからです。しかし、なぜこれはスレッドではうまくいかないでしょうか? – StewPit
'Wait Handles'を使用してください – Xaqron