0

私はマルチスレッドが初めてです。以下のいくつかの基本的な例をグーグルで検索しましたが、コードは次のとおりです

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 のスクリーンショットです。 フォーム1

4

3 に答える 3

1

「バックグラウンド」スレッドのコードは、UI スレッド上にあるかどうかを確認します

If Me.InvokeRequired Then

そうでない場合は、UI スレッドで実行するように指示します。

Me.Invoke(New MethodInvoker(AddressOf BackgroundProcess))

UI スレッド上にある場合は、ポンピングせずにループに入って UI スレッドをブロックします。

Do While True

これを機能させるには、多くの方法の 1 つが次のようになります。

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

デリゲートを使用することをお勧めします。

于 2013-09-24T13:52:01.257 に答える
0

基本的に、大量の更新で UI スレッドをホストしているため、ユーザー入力に応答する機会がありません。ループを短時間スリープに変更します。

    Do While True
        Me.ListBox1.Items.Add("Iteration:" & i)
        i += 1
        Thread.Sleep(100)
    Loop
于 2013-09-24T13:53:00.827 に答える
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))
于 2013-09-24T14:03:21.053 に答える