运行一个任务两秒不阻塞UI
Run a task for two seconds without blocking UI
我正在编写一个 VB.Net 应用程序,它与 CAN 总线交互以控制其上的一些电机。
通过 CAN 总线,我可以在正常和反向模式下打开和关闭每个电机,并读取它们的电流消耗。
我为每个电机实现了两个复选框,使其 运行 正常或反向,以及一个显示实际电流消耗的文本框,这实际上是有效的。
现在我想做的是自动化一些测试,例如:
- 运行每个电机在每个方向上两秒,并记录其消耗量以查看值是否正确。
为此,我创建了一个 TestMotor class,我在其中发送两个按钮的参考值,这两个按钮在每个电机正常或反转时打开。每个测试 class 代表每个电机的测试,所以如果我有 4 个电机,我将创建 4 个 TestMotor 对象,为它们提供两个为该电机供电的复选框。
最后,TestMotor class 有一个 executeTest,它主要 运行 通过选中和取消选中复选框在每个方向上 运行 控制电机。
这两秒延迟了它们之间的延迟。
我的问题是,如果我 运行 直接在主线程上进行那些测试, Thread.sleep 会阻塞 UI 线程,但是如果我创建一个线程然后在那里执行那些测试正在同时执行。
你会如何解决这个问题?我一直在尝试使用异步任务、计时器,现在我打算尝试一些信号量或其他东西,但如果能提供一些有关解决此问题的最佳方法的帮助就更好了。
一些代码:
主要class
for each test in test
test.executeTest()
end for
测试电机class
public sub executeTest()
ckNormal.checked = true
Thread.sleep(2000)
ckNormal.checked = false
ckReverse.checked = true
Thread.sleep(2000)
ckReverse.checked = false
end sub
谢谢!
不要使用 Thread.sleep()
使用 Task.Delay()
@StephenCleary 的回复THIS THREAD。
Use Thread.Sleep
when you want to block the current thread.
Use Task.Delay
when you want a logical delay without blocking the
current thread.
是的,我也试过了,但是如果我用异步任务执行 Task.Delay 问题是同时尝试正常和反向模式。最后我做到了:
Private Sub autocheck_btStart_Click(sender As Object, e As EventArgs) Handles autocheck_btStart.Click
If Not currentlyTesting Then
currentlyTesting = True
principal.setRecording(True, ecu)
Dim t As Task = Task.Run(Sub()
startTesting()
End Sub)
principal.setRecording(False, ecu)
currentlyTesting = False
End If
End Sub
Public Sub startTesting()
For Each test In tests
tbDebug.AppendText("Testing motor " + test.getName() + Environment.NewLine)
test.executeTest()
Next
showResults()
End Sub
Public Sub executeTest()
isTesting = True
ckNormal.Checked = True
Thread.Sleep(2000)
ckNormal.Checked = False
Thread.Sleep(200)
ckReverse.Checked = True
Thread.Sleep(2000)
ckReverse.Checked = False
Thread.Sleep(200)
isTesting = False
End Sub
感谢您的指点!!
我正在编写一个 VB.Net 应用程序,它与 CAN 总线交互以控制其上的一些电机。 通过 CAN 总线,我可以在正常和反向模式下打开和关闭每个电机,并读取它们的电流消耗。 我为每个电机实现了两个复选框,使其 运行 正常或反向,以及一个显示实际电流消耗的文本框,这实际上是有效的。 现在我想做的是自动化一些测试,例如:
- 运行每个电机在每个方向上两秒,并记录其消耗量以查看值是否正确。
为此,我创建了一个 TestMotor class,我在其中发送两个按钮的参考值,这两个按钮在每个电机正常或反转时打开。每个测试 class 代表每个电机的测试,所以如果我有 4 个电机,我将创建 4 个 TestMotor 对象,为它们提供两个为该电机供电的复选框。
最后,TestMotor class 有一个 executeTest,它主要 运行 通过选中和取消选中复选框在每个方向上 运行 控制电机。 这两秒延迟了它们之间的延迟。
我的问题是,如果我 运行 直接在主线程上进行那些测试, Thread.sleep 会阻塞 UI 线程,但是如果我创建一个线程然后在那里执行那些测试正在同时执行。
你会如何解决这个问题?我一直在尝试使用异步任务、计时器,现在我打算尝试一些信号量或其他东西,但如果能提供一些有关解决此问题的最佳方法的帮助就更好了。
一些代码:
主要class
for each test in test
test.executeTest()
end for
测试电机class
public sub executeTest()
ckNormal.checked = true
Thread.sleep(2000)
ckNormal.checked = false
ckReverse.checked = true
Thread.sleep(2000)
ckReverse.checked = false
end sub
谢谢!
不要使用 Thread.sleep()
使用 Task.Delay()
@StephenCleary 的回复THIS THREAD。
Use
Thread.Sleep
when you want to block the current thread.Use
Task.Delay
when you want a logical delay without blocking the current thread.
是的,我也试过了,但是如果我用异步任务执行 Task.Delay 问题是同时尝试正常和反向模式。最后我做到了:
Private Sub autocheck_btStart_Click(sender As Object, e As EventArgs) Handles autocheck_btStart.Click
If Not currentlyTesting Then
currentlyTesting = True
principal.setRecording(True, ecu)
Dim t As Task = Task.Run(Sub()
startTesting()
End Sub)
principal.setRecording(False, ecu)
currentlyTesting = False
End If
End Sub
Public Sub startTesting()
For Each test In tests
tbDebug.AppendText("Testing motor " + test.getName() + Environment.NewLine)
test.executeTest()
Next
showResults()
End Sub
Public Sub executeTest()
isTesting = True
ckNormal.Checked = True
Thread.Sleep(2000)
ckNormal.Checked = False
Thread.Sleep(200)
ckReverse.Checked = True
Thread.Sleep(2000)
ckReverse.Checked = False
Thread.Sleep(200)
isTesting = False
End Sub
感谢您的指点!!