简单的多线程进度条示例

Simple Multi Threading Progress Bar Example

在我的项目中,我需要通过使用进度条来通知用户某些操作的进度。 现在,我知道有大量线程在那里解释如何去做,但我尝试的每个示例似乎都没有按预期工作...

我发现做我需要的最简单的例子是在 Microsoft 支持 (here) 上,但是当我 运行 应用程序时似乎出现以下错误:

跨线程操作无效:控件 'ProgressBar1' 从创建它的线程以外的线程访问。

这是完整组织的代码:

Imports System.Threading

Public Class Form1
    Private trd As Thread

    Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
        MessageBox.Show("This is the main thread")
    End Sub

    Private Sub ThreadTask()
        Dim stp As Integer
        Dim newval As Integer
        Dim rnd As New Random()

        Do
            stp = ProgressBar1.Step * rnd.Next(-1, 2)
            newval = ProgressBar1.Value + stp
            If newval > ProgressBar1.Maximum Then
                newval = ProgressBar1.Maximum
            ElseIf newval < ProgressBar1.Minimum Then
                newval = ProgressBar1.Minimum
            End If

            ProgressBar1.Value = newval

            Thread.Sleep(100)
        Loop
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        trd = New Thread(AddressOf ThreadTask)
        trd.IsBackground = True
        trd.Start()
    End Sub
End Class

现在,在对委托和调用方法进行一些搜索和阅读之后,我在 ThreadTask 方法的开头添加了以下代码行:

If Me.InvokeRequired Then
    Me.Invoke(New Action(AddressOf ThreadTask))
    Return
End If

添加上面的代码行后,我就可以 运行 应用程序了。但是,我无法使用 btnTest 按钮,而且按钮甚至都没有绘制...

(由于声誉不佳,我仍然无法 post 图片。抱歉...)

我不知道我做错了什么。有人可以帮我吗?

您不应该调用整个方法,只调用更新进度条的代码。

而不是ProgressBar1.Value = newval

您应该将其替换为 ProgressBar1.BeginInvoke(Sub() ProgressBar1.Value = newvalue)

然而,使用 BackgroundWorker

进行这种简单的更新会更容易

如前所述,后台工作人员可以为您完成所有这些...

Dim bw As BackgroundWorker = New BackgroundWorker
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted 

然后您需要启动它并执行处理程序..

bw.runworkerasync



Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
    Try

            Dim lp As Integer = "0"

            for i = 0 to 100
                lp = lp + 1
                bw.ReportProgress((lp / sz) * 100)
            Next

        End If
    Catch x As System.Exception
        ''do some error handling

    End Try
End Sub

应将 ProgressBar1 添加到表单中

Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
    ProgressBar1.Value = e.ProgressPercentage
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)

   'do some reporting 
    ProgressBar1.Value = 0
        End Sub

我以前用过这个,我没有遇到跨线程冲突。