Imports Microsoft.VisualBasic.Parallel.Tasks ''' ''' Using parallel linq that may stuck the program when a linq task partion wait a long time task to complete. ''' By using this parallel function that you can avoid this problem from parallel linq, and also you can ''' controls the task thread number manually by using this parallel task function. ''' (由于LINQ是分片段来执行的,当某个片段有一个线程被卡住之后整个进程都会被卡住,所以执行大型的计算任务的时候效率不太好, ''' 使用这个并行化函数可以避免这个问题,同时也可以自己手动控制线程的并发数) ''' ''' Public Class ThreadTask(Of TOut) Dim taskList As Queue(Of Func(Of TOut)) Dim threads As AsyncHandle(Of TOut)() Dim size As Integer Sub New(task As IEnumerable(Of Func(Of TOut))) Me.taskList = New Queue(Of Func(Of TOut))(task) Me.size = Me.taskList.Count End Sub Public Shared Function CreateThreads(Of T)(items As IEnumerable(Of T), task As Func(Of T, Func(Of TOut))) As ThreadTask(Of TOut) Return New ThreadTask(Of TOut)(items.Select(task)) End Function Public Shared Function CreateThreads(Of T)(items As IEnumerable(Of T), task As Func(Of T, TOut)) As ThreadTask(Of TOut) Return New ThreadTask(Of TOut)(items.Select(Function(i) New Func(Of TOut)(Function() task(i)))) End Function ''' ''' You can controls the parallel tasks number from this parameter, smaller or equals to ZERO means auto ''' config the thread number, If want single thread, not parallel, set this value to 1, and positive ''' value greater than 1 will makes the tasks parallel. ''' (可以在这里手动的控制任务的并发数,这个数值小于或者等于零则表示自动配置线程的数量, 1为单线程) ''' ''' ''' Public Function WithDegreeOfParallelism(n_threads As Integer) As ThreadTask(Of TOut) threads = New AsyncHandle(Of TOut)(n_threads) {} Return Me End Function Private Function GetEmptyThread() As Integer For i As Integer = 0 To threads.Length - 1 If threads(i) Is Nothing Then Return i End If Next Return -1 End Function Private Function GetCompleteThread() As Integer For i As Integer = 0 To threads.Length - 1 If (Not threads(i) Is Nothing) AndAlso threads(i).IsCompleted Then Return i End If Next Return -1 End Function Public Overrides Function ToString() As String Dim free$ = threads.Where(Function(t) t Is Nothing).Count Dim running$ = threads.Where(Function(t) t IsNot Nothing AndAlso Not t.IsCompleted).Count Dim finished$ = threads.Where(Function(t) t IsNot Nothing AndAlso t.IsCompleted).Count Dim delta As Integer = size - taskList.Count Return $"[free: {free}, running: {running}, finished: {finished}, progress: {delta} - {CInt(delta / size * 100)}%]" End Function ''' ''' ''' ''' Public Iterator Function RunParallel() As IEnumerable(Of TOut) Do While taskList.Count > 0 Dim i As Integer = GetEmptyThread() If i > -1 Then threads(i) = New AsyncHandle(Of TOut)(taskList.Dequeue).Run Call Console.WriteLine($"{ToString()} submit new task on thread [{i + 1}]!") End If Dim j As Integer = GetCompleteThread() If j > -1 Then Yield threads(j).GetValue threads(j) = Nothing Call Console.WriteLine($"{ToString()} [thread_{j + 1}] job done!") End If Loop Do While Not threads.All(Function(t) t Is Nothing) Dim j As Integer = GetCompleteThread() If j > -1 Then Yield threads(j).GetValue threads(j) = Nothing Call Console.WriteLine($"{ToString()} [thread_{j + 1}] job done!") End If Loop End Function End Class