为什么这个简单的多线程不起作用.UI变得反应迟钝

时间:2013-09-24 13:46:29

标签: vb.net multithreading delegates visual-studio-2005

我是多线程的新手。我用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的截图 Form1

3 个答案:

答案 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))