简单的多线程进度条示例
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
我以前用过这个,我没有遇到跨线程冲突。
在我的项目中,我需要通过使用进度条来通知用户某些操作的进度。 现在,我知道有大量线程在那里解释如何去做,但我尝试的每个示例似乎都没有按预期工作...
我发现做我需要的最简单的例子是在 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
我以前用过这个,我没有遇到跨线程冲突。