我试图创建一个多线程程序来轮询机器的数据,但似乎无法使其正常工作。下面的代码正在工作,并创建了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.
}