出现问题是因为您将 UI 线程置于睡眠状态。在 .NET 4.5 中,您可以使用Task.Delay
使您的代码仅在特定时间间隔后执行而不阻塞任何线程,例如:
Dim port As New SerialPort
...
Public Async Sub SomeButton_Click()
port.WriteLine("First")
Await Task.Delay(500)
port.WriteLine("Second")
Await Task.Delay(300)
port.WriteLine("Third")
End Sub
在这种情况下,第一次WriteLine
在 UI 线程上执行,在后台等待 500 毫秒(实际上使用计时器),然后在原始线程(UI 线程)上恢复执行,第二次WriteLine
也在 UI 线程中发生。再等待 300 毫秒,然后第三个 WriteLine 也出现在 UI 线程中。
这种Async\Await
组合允许您以非常干净的方式编写此类代码,而无需涉及诸如 BackgroundWorker 之类的其他组件。它还允许您执行 Background Worker 无法执行的操作,例如执行多个异步调用。在这种情况下,您需要使用多个工作人员,现在您只需再编写一个语句
请注意,该Async Sub
语法仅用于事件处理程序。在所有其他情况下,您应该使用Async Function SomeFunction() As Task
.
如果要在后台线程中运行整个序列,可以使用Task.Run
.
Public Async Sub SomeButton_Click()
Task.Run(Async Function ()
Await SendAndWait
End Function)
End Sub
public Async Function SendAndWait As Task
_port.WriteLine("First")
Await Task.Delay(500)
_port.WriteLine("Second")
Await Task.Delay(300)
_port.WriteLine("Third")
End Function
使用 Tasks 的真正美妙之处在于,您可以组合多个异步操作,这在 BackgroundWorker 中几乎是不可能的。在这种情况下,您可以从文件或数据库中异步读取数据,然后将其异步发送到串口,代码非常简单:
public Async Function SendAndWait(filePath As String) As Task
Dim line As String
Using reader As New StreamReader(filePath)
For i=0 To 3
line=Await reader.ReadLineAsync()
_port.WriteLine(line)
Await Task.Delay(500)
Next
End Using
End Function
您也可以通过将Microsoft.Bcl.Async包添加到您的项目中来使用async/await
.NET 4.0 代码中的关键字。