关键词搜索

源码搜索 ×
×

VB.net WinForm如何写一个分线程进度条

发布2021-02-10浏览654次

详情内容

首先, 我们先来看一个长耗时过程

Private Sub ValueTest()       
    For i As Integer = 0 To 100
        ProgressBar1.Value = i 
        Threading.Thread.Sleep(1000)
    Next
End Sub

    我们会发现,在100时间内,窗体无法被移动,进度条也不会移动(win10的UI可以移动,但任然看起来很卡),等循环完毕后进度条突然就满了。
    懂UI窗体运行原理的都知道,程序的主线程不仅仅要处理我们写的代码,还要刷新UI的界面。当在处理长耗时过程时,UI界面也会被“锁死”,直到过程被执行完毕。
    有些懂线程委托的小朋友就要说了,用分线程委托嘛,例如这样:

      Private Sub ValueTest_Thread()
            For i As Integer = 0 To 100
                ChangePBValue(i, ProgressBar1)
                Threading.Thread.Sleep(1000)
            Next
        End Sub
        Private Sub ChangePBValue(_Value As Integer, ByRef _PB As ProgressBar)
            If _PB.InvokeRequired = True Then
                _PB.BeginInvoke(New D_ChangePBValue(AddressOf ChangePBValue), _Value, _PB)
            Else
                _PB.Value = _Value
            End If
        End Sub
        Private Delegate Sub D_ChangePBValue(_Value As Integer, ByRef _PB As ProgressBar)
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim NT As New Threading.Thread(AddressOf ValueTest_Thread)
            NT.Start()
        End Sub
    
      7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    萌新们表示看起来很困难,我这里不过多解释怎么创建分线程了,自己百度一下跨线程更新控件方法与原理。
    我给大家说一下分线程窗体的调用方法

    Private Sub ValueTest_ThreadForm()
        ThreadPBManger.Start("我想表达点什么呢???")
        For i As Integer = 0 To 100
            ThreadPBManger.SetValue(i)
            Threading.Thread.Sleep(100)
        Next
        ThreadPBManger.Stop()
    End Sub
    
      7
    • 8

    好像很简单啊,这样就可以在主线程完全卡死的情况下也能在进度条中显示进度了,还能报告在做什么内容,好神奇,但是ThreadPBManger是什么鬼?

    Public Module ThreadPBManger
        Dim NF_PB As F_PB
        Public Sub Start(ShowStr As String)
            Dim NT As New Threading.Thread(AddressOf Start_thread)
            NT.Start(ShowStr)
        End Sub
        Private Sub Start_thread(ShowStr As String)
            NF_PB = New F_PB
            NF_PB.Text = ShowStr
            Application.Run(NF_PB)
        End Sub
        Public Sub SetValue(Value As Integer)
            If IsNothing(NF_PB) Then Return
            If NF_PB.IsDisposed Then Return
            ChangePBValue(Value, NF_PB.ProgressBar1)
        End Sub
        Private Delegate Sub D_Stop()
        Public Sub [Stop]()
            If IsNothing(NF_PB) Then Return
            If NF_PB.IsDisposed Then Return
            If NF_PB.InvokeRequired Then
                NF_PB.Invoke(New D_Stop(AddressOf [Stop]))
            Else
                NF_PB.Dispose()
            End If
        End Sub
    
    #Region "委托更新PB"
        Public Sub ChangePBValue(_Value As Integer, ByRef _PB As ProgressBar)
            If _PB.InvokeRequired = True Then
                _PB.BeginInvoke(New D_ChangePBValue(AddressOf ChangePBValue), _Value, _PB)
            Else
                _PB.Value = _Value
            End If
        End Sub
        Private Delegate Sub D_ChangePBValue(_Value As Integer, ByRef _PB As ProgressBar)
    #End Region
    End Module
    
      7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    源码位置 https://download.csdn.net/download/meiren777/10762052

    知识点
    Delegate,线程委托,BeginInvoke,InvokeRequired

    重点解释

    Application.Run:在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。以该模式打开窗体后,该线程窗体将持续响应消息循环,该线程只会随着窗体的关闭而关闭。一个线程只有存在一个消息循环。当前执行位置将会停止在此,当制定窗体关闭后,继续执行后面的代码。
    PS

    实际使用过程中,需要小伙伴们美化窗体,并添加vb.net教程更多的Try Catch来处理具体的异常。
    有趣的是Devexpress提供了SplashScreenManager提供了完整的线程进度窗体解决方案,我们叫它飞溅窗体。基础版使用相对简单,但要使用自定义窗体其难度非常高,后面我开文章教大家如何使用Devexpress的控件(想想脑壳疼,好大的项目啊!)

    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载