The problem occurs because you are putting the UI thread to sleep. In .NET 4.5, you can use Task.Delay
to make your code execute only after a certain interval without blocking any thread, eg:
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
In this case the first WriteLine
executes on the UI thread, a wait occurs in the background for 500ms (actually using a timer), then execution resumes on the original thread (the UI thread) and the second WriteLine
occurs in the UI thread as well. Another 300 ms wait then the third WriteLine occurs in the UI thread as well.
The Async\Await
combination allows you to write such code in a very clean manner, without involving other components like BackgroundWorker. It also allows you to do things that Background Worker just can't do, like execute multiple asynchronous calls. In such a case you would need to use multiple workers where now you just write one more statement
Note that the Async Sub
syntax is used only for event handlers. In all other cases you should use Async Function SomeFunction() As Task
.
If you want to run the entire sequence in a background thread, you can use 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
The real beauty of using Tasks, is that you can combine multiple asynchronous operations, something that's nearly impossible with BackgroundWorker. In this case, you can read data from a file or database asynchronously and send it to the serial port asynchronously, with very simple code:
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
You can use the async/await
keywords in .NET 4.0 code as well by adding the Microsoft.Bcl.Async package to your project.