我有/ for next循环,我下载一个文件,然后处理并将其contnets加载到数据库中:
For Each f As WinSCP.RemoteFileInfo In remotefilesinf
If DownloadFile(FTPSession, CacheDirPath, "/mnt/usb", f) Then
LoadDB(System.IO.Path.Combine(CacheDirPath, f.Name))
Else
MsgBox("Download failed.")
End If
Next
为了加快速度,在下载下一个文件时如何进行数据库加载?在每个文件下载完成之前,我无法执行DBLoad,并且由于数据库的锁定,我一次只能执行一个DBLoad任务。
我尝试使用后台工作程序来执行LoadDB任务,但是当UI线程忙于下载时,RunWorkerCompleted事件不会触发,因此我不知道何时可以执行下一个DBload(DB未锁定)。
任何建议表示赞赏。
答案 0 :(得分:2)
这是另一个尝试,因为问题的要求已经改变:
Public Class Form1
Shared rnd As New Random
Private download_que As New Queue(Of String)
Private process_que As New Queue(Of String)
Private download_thread As Thread
Private process_thread As Thread
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
download_que.Enqueue("File 1.db")
download_que.Enqueue("File 2.db")
download_que.Enqueue("File 3.db")
download_que.Enqueue("File 4.db")
download_que.Enqueue("File 5.db")
download_que.Enqueue("File 6.db")
If download_thread Is Nothing then
download_thread = New Thread(AddressOf DownloadFiles)
download_thread.Start()
End If
End Sub
Private AppendTextCaller As New Action(Of TextBox, String)(AddressOf AppendText)
Public Sub AppendText(ByVal control As TextBox, ByVal text As String)
control.AppendText(text)
End Sub
Public Sub DownloadFiles()
Dim file As String
While download_que.Count > 0
SyncLock download_que
file = download_que.Dequeue()
End SyncLock
Dim path As String = Download(file)
SyncLock process_que
process_que.Enqueue(path)
End SyncLock
If process_thread Is Nothing Then
process_thread = New Thread(AddressOf ProcessFiles)
process_thread.Start()
End If
End While
download_thread = Nothing
End Sub
Public Sub ProcessFiles()
Dim path As String, ok As Boolean
ok = True
While process_que.Count > 0 And ok
SyncLock process_que
path = process_que.Dequeue()
End SyncLock
ok = LoadDB(path)
End While
process_thread = Nothing
End Sub
Public Function Download(ByVal filename As String) As String
Dim sw = Stopwatch.StartNew()
Me.Invoke(AppendTextCaller, TextBox1, filename)
Thread.Sleep(1500 + 500*rnd.Next(15))
Dim message As String = String.Format(" ({0:F1} sec)", sw.ElapsedMilliseconds / 1000)
Me.Invoke(AppendTextCaller, TextBox1, message)
Me.Invoke(AppendTextCaller, TextBox1, Environment.NewLine)
Return IO.Path.Combine(IO.Path.GetTempPath(), filename)
End Function
Public Function LoadDB(ByVal path As String) As Boolean
Dim sw = Stopwatch.StartNew()
Dim filename = IO.Path.GetFileName(path)
Me.Invoke(AppendTextCaller, TextBox2, filename)
Thread.Sleep(800 + 500*rnd.Next(6))
Dim message As String = String.Format(" ({0:F1} sec)", sw.ElapsedMilliseconds / 1000)
Me.Invoke(AppendTextCaller, TextBox2, message)
Me.Invoke(AppendTextCaller, TextBox2, Environment.NewLine)
Return True
End Function
End Class
答案 1 :(得分:0)
使用两名背景工作者怎么样?使用一个下载文件,另一个将它们填入数据库。 如果下载完成,请将文件附加到列表中,每次db更新完成时,从bgw2查看该列表...
答案 2 :(得分:0)
您可以在线程上运行DBLoad
并设置ManualResetEvent
以在执行新DBLoad
线程之前停止执行,直到另一个完成。
Dim locker as New ManualResetEvent(True)
locker
就像交通信号灯一样,停止执行并等待标记时间,否则等待。
使用以下地址阻止locker
:
locker.Reset()
使用以下地址取消阻止locker
:
locker.Set()
设置一个停止点:
locker.WaitOne()
要查看完整功能,请参阅MSDN。
答案 3 :(得分:0)
我认为这就是你想要的:
Public Function DownLoadFile(ByVal f As String) As String
Trace.WriteLine("Start Downloading " & f)
Dim x As Integer = ProgressBar1.Value
Threading.Thread.Sleep(2000)
Me.Invoke(SetProgressCaller, x + 25)
Trace.WriteLine("Done Downloading " & f)
Return IO.Path.Combine(IO.Path.GetTempPath(), f)
End Function
Public Sub LoadDB(ByVal f As String)
Trace.WriteLine("Start Loading " & f)
Dim x As Integer = ProgressBar1.Value
Threading.Thread.Sleep(1000)
Me.Invoke(SetProgressCaller, x + 25)
Trace.WriteLine("Done Loading " & f)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ProgressBar1.Value = 0
Dim f_path_1 = DownLoadFile("File 1")
Dim t1 As New Threading.Thread(AddressOf LoadDB)
t1.Start(f_path_1)
ProgressBar1.Value = 50
Dim f_path_2 = DownLoadFile("File 2")
Dim t2 As New Threading.Thread(AddressOf LoadDB)
t2.Start(f_path_2)
End Sub
' Can be called using Form.Invoke() from any thread
Private SetProgressCaller As New Action(Of Integer)(AddressOf SetProgress)
' Set progress bar in main thread
Public Sub SetProgress(ByVal pct As Integer)
ProgressBar1.Value = pct
End Sub
结果:
Start Downloading File 1
Done Downloading File 1
Start Downloading File 2
Start Loading C:\Users\#####\AppData\Local\Temp\File 1
Done Loading C:\Users\#####\AppData\Local\Temp\File 1
Done Downloading File 2
Start Loading C:\Users\#####\AppData\Local\Temp\File 2
Done Loading C:\Users\#####\AppData\Local\Temp\File 2
转换为