我是多线程的新手。我用Google搜索了一些基本的例子是代码
Imports System.Threading
Public Class Form1
Dim t As New Thread(AddressOf Me.BackgroundProcess)
Private Sub btnStartThread_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartThread.Click
t.Start()
End Sub
Private Sub StopButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopButton.Click
t.Abort()
End Sub
Public Sub BackgroundProcess()
Dim i As Integer = 1
If Me.InvokeRequired Then
Me.Invoke(New MethodInvoker(AddressOf BackgroundProcess))
Else
Do While True
Me.ListBox1.Items.Add("Iteration:" & i)
i += 1
Loop
End If
End Sub
End Class
当我点击开始线程时,我的UI变得没有响应。这背后的原因是什么。下面是UI的截图
答案 0 :(得分:1)
你的代码在"背景"线程检查它是否在UI线程上
If Me.InvokeRequired Then
如果没有,它会告诉它在UI线程上运行。
Me.Invoke(New MethodInvoker(AddressOf BackgroundProcess))
如果它在UI线程上,它就会处于一个循环中,阻塞UI线程,而不会抽空。
Do While True
为了实现这一点,许多方法之一就是这样:
Public Delegate Sub AddItemDelegate(ByVal item As Object)
Public Sub BackgroundProcess()
Dim i As Integer = 1
Do While True
i += 1
If Me.InvokeRequired Then
Me.Invoke(New AddItemDelegate(AddressOf AddItem), "Iteration:" & i)
Else
AddItem("Iteration:" & i)
End If
Loop
End Sub
Private Sub AddItem(ByVal item As Object)
Me.ListBox1.Items.Add(item)
End Sub
使用委托是首选方式。
答案 1 :(得分:0)
你基本上是通过大量更新来填充UI线程,因此它永远不会有机会响应用户输入。将循环更改为睡眠状态一小段时间。
Do While True
Me.ListBox1.Items.Add("Iteration:" & i)
i += 1
Thread.Sleep(100)
Loop
答案 2 :(得分:0)
在运行代码时,UI没有响应,因为UI在很短的时间内收到大量更新,要么阻止循环无限:
Do While True
Me.ListBox1.Items.Add("Iteration:" & i)
If i > 10 Then
Exit Do
End If
i += 1
Loop
或者在每次循环后添加一个等待计时器以减慢UI更新的频率:
Do While True
Me.ListBox1.Items.Add("Iteration:" & i)
i += 1
'Sleep for 1 second
Thread.CurrentThread.Sleep(1000)
Loop
此外,您应该停止在UI线程上运行的代码,因为您当前正在创建一个线程,然后在UI线程上运行一些东西,这对我来说似乎是不需要的。
即。改变
Me.InvokeRequired
要
ListBox1.InvokeRequired
并且
Me.Invoke(New MethodInvoker(AddressOf BackgroundProcess))
要
ListBox1.Invoke(New MethodInvoker(AddressOf BackgroundProcess))