出现问题是因为您将 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 代码中的关键字。