简单的多线程进度条示例

时间:2015-07-31 13:15:47

标签: .net vb.net multithreading progress-bar invoke

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

我发现做我需要的最简单的例子是在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

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

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

在添加上面的代码行后,我能够运行该应用程序。但是,我无法使用 btnTest 按钮,甚至没有绘制按钮......

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

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

2 个答案:

答案 0 :(得分:1)

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

而不是ProgressBar1.Value = newval

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

然而,使用BackgroundWorker

进行此类简单更新会更容易

答案 1 :(得分:0)

如上所述,背景工作者可以为你做这一切......

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

之前我使用过这个,但我没有违反交叉线程。