VB.NET多線程入門


近期項目中遇到了一個處理速度慢阻塞用戶界面操作的問題,因此想用多線程來解決。

在處理數據的循環中,新建線程,在新建的線程中處理數據。多線程同一時候處理數據,以此來達到加速的目的,使用戶界面操作變得流暢。

在多任務操作系統中。我們能夠在操作系統的協調下同一時候進行多個任務。各個任務以分時復用的形式來進行工作。

Windows操作系統通過進程ID來管理各進程。每一個進程至少包括一個線程。線程是進程中能夠獨立執行的程序片段。在主程序執行時,主程序能夠啟動線程。線程與主程序同一時候執行。

線程是系統中分時處理的最小單位,也就是說線程能夠與主程序並行執行。參與同分時處理。線程有自己獨立的棧處理數據。它在與主程序同一時候執行時能夠共享主程序定義的變量、函數。僅僅有當線程執行結束才把控制權還給主程序。

創建線程最直接的方法是創建新的線程類實例,並使用Address Of語句為執行的過程傳遞托付。

可是這樣的方法不能傳遞參數和返回值。

我們能夠通過將在單獨的線程中執行的過程包裝到類或結構中。為它們提供參數,並使之能返回參數。

以下是一個新建線程的小demo:

Class TasksClass
    Public StrArg As String
    Public RetVal As Boolean
    Public resultFlag As Boolean

    Public Event ResultEvent(ByVal resultFlag As Boolean)

    Public Sub SomeTask()
        ' 將 StrArg 字段用作參數。
        MessageBox.show("StrArg 包括字符串" & StrArg)
        RetVal = True ' 設置返回參數的返回值。

End Sub End Class

Public Class Test

    Private Sub Test_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        DoWork()
    End Sub

    ' 要使用類。請設置存儲參數的屬性或字段,
    ' 然后。依據須要異步調用方法。

Sub DoWork() Dim Tasks As New TasksClass() Dim Thread1 As New System.Threading.Thread(AddressOf Tasks.SomeTask) Tasks.StrArg = "參數A" ' 設置用作參數的字段。 Thread1.Start() ' 啟動新線程。 Thread1.Join() ' 等待線程 1 執行結束。

' 顯示返回值。

MessageBox.show("線程 1 返回值" & Tasks.RetVal) End Sub End Class

這樣一個線程就被新建出來了。


可是其實。創建過多的線程反而會影響性能。由於各個線程之間是分時復用的,操作系統須要在它們之間不斷的切換。線程過多的時候,大量的時間消耗在線程切換上。

所以須要控制線程的數量。

如果我們僅僅新建10個線程,剩余的數據等待這10個線程中的某個結束,再繼續新建線程處理數據。

使線程的總數一直保持在10個。

Public Class ThreadingObj
    Public paper As WorkSpace
    Public Sub ThreadingInsertPaper()
        '多線程處理數據
    End Sub
End Class
Private PaperList As List(Of WorkSpace) = New List(Of WorkSpace)
Dim ThreadingList As List(Of System.Threading.Thread) = New List(Of System.Threading.Thread)
For Each paper In PaperList
    '多線程處理PaperList
    If ThreadingList.Count < 10 Then  
    '不到10個線程則繼續新起線程  
        Dim ThreadingObject As New ThreadingObj  
        Dim ThreadingTask_1 As New System.Threading.Thread(AddressOf ThreadingObject.ThreadingInsertPaper)  
        ThreadingObject.paper = paper  
        ThreadingList.Add(ThreadingTask_1)  
        ThreadingTask_1.Start() ' 啟動新線程。  
    Else  
        Dim goOnFlag As Boolean = False  
        '循環等待有線程結束  
        Do  
            If CheckThreadingStatus() Then  
                '存在已完畢的線程  
                If ThreadingList.Count <= 10 Then  
                    Dim ThreadingObject As New ThreadingObj  
                    Dim ThreadingTask_1 As New System.Threading.Thread(AddressOf ThreadingObject.ThreadingInsertPaper)  
                    ThreadingObject.paper = paper  
                    ThreadingList.Add(ThreadingTask_1)  
                    ThreadingTask_1.Start() ' 啟動新線程。  
                    goOnFlag = True  
                End If  
            Else  
                '全部線程都在進行中  
            End If  
        Loop Until goOnFlag = True  
    End If
Next
Function CheckThreadingStatus() As Boolean
    '返回True表示存在已完畢的線程
    If ThreadingList.Count <= 10 Then
        For Each ThreadingTaskItem In ThreadingList
            'ThreadingTaskItem.IsAlive
            If ThreadingTaskItem.IsAlive = False Then
                ThreadingTaskItem.Abort()
                ThreadingList.Remove(ThreadingTaskItem)
                Return True
            End If
        Next
    End If
    Threading.Thread.Sleep(100)
    If ThreadingList.Count <= 10 Then
        For Each ThreadingTaskItem In ThreadingList
            If ThreadingTaskItem.IsAlive = False Then
                Return True
            End If
        Next
    End If
    Return False
End Function

如果操作系統中有50個活躍的線程。如果我們的程序僅僅有一個線程。那么程序就占用了系統資源的五十分之中的一個。如果此時再多開一個線程,那么就占用了系統資源的2/51。我們的程序占用的資源越多。處理速度也就會更快一些。

由於各個線程之間是分時復用的,所以活躍的線程數量也會影響程序的效率。

有一種說法是2N + 2個線程數。是最有效率的。N是CPU的核數。

可是這一說法也一直存在爭議。

我的測試結果例如以下(我的電腦是i7 4770 。四核八線程):

線程數 1 2 3 4 5 6 7 8 9 10 11 15
耗時 753 409 345 316 305 286 280 282 273 273 264 266

測試的結果有點奇怪。。

。。

可能跟一些其它的因素也有關系。

比方DB的狀態,比方瀏覽網頁對CPU的占用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM