使用参数化函数(x,y,z)的 for 循环中的多个线程
Multiple threads in a for-loop using a parameterized function(x, y, z)
我有一个包含文件夹 ID 和文件夹路径的列表。我想将其中一些文件夹传递给一个压缩它们的函数。我想要的是并行三个线程 运行 并一次压缩三个不同的路径。现在发生的是每个线程等待直到下一个线程完成才能处理下一个。有什么想法吗?
Dim SelectedRange = From folders In listFolders Where folders.FolderID >= 150101
For Each item In SelectedRange
Dim t As New Thread(
Sub()
Me.BeginInvoke(DirectCast(Sub() ZipFolder(sInclearDestination, item.FolderID.ToString, item.FolderPath), MethodInvoker))
End Sub)
t.Start()
t.Join()
Next
Public Function ZipFolder(ByVal sFolderPathDestination As String, ByVal folderID As String, ByVal folderPath As String) As Boolean
Try
Using zip = New Ionic.Zip.ZipFile()
'If the zip file does not exist then get the folder and zip it to the destination
If Not File.Exists(Path.Combine(sFolderPathDestination, folderID & ".zip")) Then
zip.AddDirectory(folderPath)
zip.Save(Path.Combine(sFolderPathDestination, CType(folderID, String) & ".zip"))
Return True
Else
Logging.Log("Aborting zipping: " & Path.Combine(sFolderPathDestination, folderID & ".zip") & ". The zip file already exists!")
Return False
End If
End Using
Catch ex As Exception
Logging.Log("Error in zipping: " & Path.Combine(sFolderPathDestination, folderID & ".zip") & " Error: " & ex.Message)
Return False
End Try
End Function
您的代码有两个问题。
第一个问题是对Me.BeginInvoke
的调用。假设您正在创建一个 WinForm 应用程序并且 Me
是对当前 Form
的引用。 Form.BeginInvoke
(继承自基础 Control
class)导致给定的委托在 UI 线程上执行。因此,您所做的就是创建三个独立的线程,它们都立即调用回 UI 线程来完成它们的所有工作。您显然不能那样做,并且仍然希望并行处理这些任务。您需要删除对 BeginInvoke
的调用。如果您需要调用 BeginInvoke
以更新表单上某些数据的显示,您需要尽可能晚地执行此操作,并在 UI 调用的代码中做尽可能少的工作这样大部分工作仍在工作线程中完成。
第二个问题是对Thread.Join
的调用。您在启动线程后立即在 For
循环中调用 Join
。这意味着它将坐在那里等待,在调用 Join
时,直到工作线程完成。因此,您的循环在开始下一个线程之前等待每个线程完成,本质上,使其成为单线程。您应该只删除对 Join
的调用。如果您需要调用方法等待所有线程完成,只需等待在线程上调用 Join
直到 all 它们已经启动(即在 For
循环)。
我有一个包含文件夹 ID 和文件夹路径的列表。我想将其中一些文件夹传递给一个压缩它们的函数。我想要的是并行三个线程 运行 并一次压缩三个不同的路径。现在发生的是每个线程等待直到下一个线程完成才能处理下一个。有什么想法吗?
Dim SelectedRange = From folders In listFolders Where folders.FolderID >= 150101
For Each item In SelectedRange
Dim t As New Thread(
Sub()
Me.BeginInvoke(DirectCast(Sub() ZipFolder(sInclearDestination, item.FolderID.ToString, item.FolderPath), MethodInvoker))
End Sub)
t.Start()
t.Join()
Next
Public Function ZipFolder(ByVal sFolderPathDestination As String, ByVal folderID As String, ByVal folderPath As String) As Boolean
Try
Using zip = New Ionic.Zip.ZipFile()
'If the zip file does not exist then get the folder and zip it to the destination
If Not File.Exists(Path.Combine(sFolderPathDestination, folderID & ".zip")) Then
zip.AddDirectory(folderPath)
zip.Save(Path.Combine(sFolderPathDestination, CType(folderID, String) & ".zip"))
Return True
Else
Logging.Log("Aborting zipping: " & Path.Combine(sFolderPathDestination, folderID & ".zip") & ". The zip file already exists!")
Return False
End If
End Using
Catch ex As Exception
Logging.Log("Error in zipping: " & Path.Combine(sFolderPathDestination, folderID & ".zip") & " Error: " & ex.Message)
Return False
End Try
End Function
您的代码有两个问题。
第一个问题是对Me.BeginInvoke
的调用。假设您正在创建一个 WinForm 应用程序并且 Me
是对当前 Form
的引用。 Form.BeginInvoke
(继承自基础 Control
class)导致给定的委托在 UI 线程上执行。因此,您所做的就是创建三个独立的线程,它们都立即调用回 UI 线程来完成它们的所有工作。您显然不能那样做,并且仍然希望并行处理这些任务。您需要删除对 BeginInvoke
的调用。如果您需要调用 BeginInvoke
以更新表单上某些数据的显示,您需要尽可能晚地执行此操作,并在 UI 调用的代码中做尽可能少的工作这样大部分工作仍在工作线程中完成。
第二个问题是对Thread.Join
的调用。您在启动线程后立即在 For
循环中调用 Join
。这意味着它将坐在那里等待,在调用 Join
时,直到工作线程完成。因此,您的循环在开始下一个线程之前等待每个线程完成,本质上,使其成为单线程。您应该只删除对 Join
的调用。如果您需要调用方法等待所有线程完成,只需等待在线程上调用 Join
直到 all 它们已经启动(即在 For
循环)。