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

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

    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

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

    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

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

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

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

重点解释

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

PS

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值