在我的项目中,我需要通过使用进度条通知用户某些操作的进度。 现在,我知道有很多线程在那里解释如何做,但我尝试的每个例子似乎都没有按预期工作......
我发现做我需要的最简单的例子是在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 按钮,甚至没有绘制按钮......
(由于声誉不佳,我仍然无法发布图片。抱歉......)
我不知道我做错了什么。愿有人帮帮我吗?
答案 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
之前我使用过这个,但我没有违反交叉线程。