Vb.net多线程不工作.



我试图创建一个多线程程序来轮询机器的数据,但似乎无法使其正常工作。下面的代码正在工作,并创建了4个线程,但代码流似乎是串行发生的,并且在主UI线程上。

我试图实现的是让数据网格的每一行同时更新,而不锁定UI。

下面是我所拥有的一个简单的版本,但它可以证明这个问题。为了提供信息,"testclass"是一个用作机器实例的类,每个类元素代表机器的一个属性。

希望我已经提供了足够的信息来解释这个问题。提前谢谢。

Ps我不应该刷新表单,是吗?

Imports System.Threading
Public Class TestForm
Public threadcount As Integer
Public Delegate Sub testclassDelegate(test As Object)
Private Class testclass
    Public index As Integer
    Public TestVal1 As Integer = 100
    Public TestVal2 As Integer = 200
    Public TestVal3 As Integer = 300
    Public TestVal4 As Integer = 400
    Public TestVal5 As Integer = 500
    Public TestVal6 As Integer = 600
    Public testDel As testclassDelegate
End Class
Private Sub TestForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    For i As Integer = 0 To 3
        DataGridView1.Rows.Add()
        DataGridView1.Rows(i).Cells(0).Value = i + 1
    Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    For i As Integer = 0 To 3
        DataGridView1.Rows(i).Cells(1).Value = ""
        DataGridView1.Rows(i).Cells(2).Value = ""
        DataGridView1.Rows(i).Cells(3).Value = ""
        DataGridView1.Rows(i).Cells(4).Value = ""
        DataGridView1.Rows(i).Cells(5).Value = ""
        DataGridView1.Rows(i).Cells(6).Value = ""
    Next
    Poll_FreeThread()
End Sub
Private Sub Poll_FreeThread()
    For i As Integer = 0 To DataGridView1.Rows.Count - 1
        Dim test As New testclass
        test.index = i
        test.testDel = AddressOf UIUpdate
        Interlocked.Increment(threadcount)
        Me.Label2.Text = threadcount
        Try
            Dim thPoll As New Thread(Sub() invokeUIUpdate(test))
            thPoll.IsBackground = True
            thPoll.Priority = ThreadPriority.BelowNormal
            thPoll.Start()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    Next
End Sub
Public Sub invokeUIUpdate(test As Object)
    If DataGridView1.InvokeRequired Then
        DataGridView1.Invoke(New testclassDelegate(AddressOf UIUpdate), test)
    Else
        UIUpdate(test)
    End If
End Sub
Public Sub UIUpdate(test As Object)
    Thread.Sleep(test.index * 100)
    DataGridView1.Rows(test.index).Cells(1).Value = test.TestVal1
    Me.Refresh()
    Thread.Sleep(100)
    DataGridView1.Rows(test.index).Cells(2).Value = test.TestVal2
    Me.Refresh()
    Thread.Sleep(100)
    DataGridView1.Rows(test.index).Cells(3).Value = test.TestVal3
    Me.Refresh()
    Thread.Sleep(100)
    DataGridView1.Rows(test.index).Cells(4).Value = test.TestVal4
    Me.Refresh()
    Thread.Sleep(100)
    DataGridView1.Rows(test.index).Cells(5).Value = test.TestVal5
    Me.Refresh()
    Thread.Sleep(100)
    DataGridView1.Rows(test.index).Cells(6).Value = test.TestVal6
    Me.Refresh()
    Interlocked.Decrement(threadcount)
    Me.Label2.Text = threadcount
End Sub
End Class

运行您的代码有点不同,这就是vb.net中多线程的结构应该是什么样子的(这与vb.net没有根据我的理解将命名空间传递到模型中有关)

这将是您从加载中的MainThread启动线程,或者让您

Private Sub DoSomethingSimple()
    Dim DoSomethingSimple_Thread As New Thread(AddressOf DoSimple)
    DoSomethingSimple_Thread.Priority = ThreadPriority.AboveNormal
    DoSomethingSimple_Thread.Start(Me)
End Sub

这将是实际的线程Itself(新模型/类或在同一类中)

Private Sub DoSimple(beginform As Form)
    'Do whatever you are doing that has nothing to do with ui
    'For UI calls use the following
    SomethingInvoked(PassibleVariable, beginform)
End Sub

为对主线程的每次调用编写一个委托和Invoke方法

Delegate Sub SomethingInvoked_Delegate(s As Integer, beginform As Form)
Sub SomethingInvoked_Invoke(ByVal s As Integer, beginform As Form)
    If beginform.NameOfControlYouAreUpdating.InvokeRequired Then ' change NameOfControlYouAreUpdating to the Name of Control on the form you wish to update
        Dim d As New SomethingInvoked_Delegate(AddressOf SomethingInvoked_Invoke)
        beginform.Invoke(d, New Object() {s, beginform})
    Else
        'Do something...
        beginform.NameOfControlYouAreUpdating.Condition = Parameter
    End If
End Sub

这是在vb.net 中测试(非挂起)的线程编写方式

如果您需要进一步帮助实现此模板的代码,请告诉我:p

您可以将计时器和后台工作者与DoWorkEventHandler和RunWorkerCompletedEventHandler的事件一起使用。

示例:C#示例:

private void Button1_Click(object sender, EventArgs e)
{
workerThreadForLetters.WorkerReportsProgress = true;                    workerThreadForLetters.WorkerSupportsCancellation = true;
workerThreadForLetters.DoWork -= new DoWorkEventHandler(workerThreadForLetters_DoWork);
workerThreadForLetters.DoWork += new DoWorkEventHandler(workerThreadForLetters_DoWork);
workerThreadForLetters.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(workerThreadForLetters_RunWorkerCompleted);
workerThreadForLetters.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThreadForLetters_RunWorkerCompleted);
}
    private void workerThreadForLetters_DoWork(object sender, DoWorkEventArgs e)
    {
               //DO SOMETHING
    }
    private void workerThreadForLetters_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
             //DO AS REQUIRED
             Timer1.enable = false;
    }
    private void tmCollectionLettersUpdate_Tick(object sender, EventArgs e)
    {
             //Content update like % of data progressed or any.
    }

最新更新