Проблема возникает потому, что вы ставите нить 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
выполняет в потоке пользовательского интерфейса, ожидание происходит в фон на 500 мс (фактически с использованием таймера), затем выполнение возобновляется в исходном потоке (поток пользовательского интерфейса), а второй WriteLine
также встречается в потоке пользовательского интерфейса. Еще 300 мс ждут, тогда третья запись также встречается в потоке пользовательского интерфейса.
Комбинация Async\Await
позволяет вам написать такой код очень чистым способом, не включая другие компоненты, такие как BackgroundWorker. Он также позволяет делать то, что не может сделать фоновый рабочий, например выполнить несколько асинхронных вызовов. В таком случае вам нужно будет использовать несколько сотрудников, где теперь вы просто напишите еще одно заявление
Обратите внимание, что синтаксис 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
Реальная красота с помощью задач, является то, что вы можете объединить несколько асинхронных операций, то, что это почти невозможно с 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
Вы можете использовать в async/await
ключевые слова в .NET 4.0 код, а также путем добавления пакет Microsoft.Bcl.Async к вашему проекту.
Почему бы просто не сделать это в рабочем потоке? –
Хорошо, я на нем! Благодаря! – KRC
Почему вы используете COM-компонент вместо .NET [SerialPort] (http://msdn.microsoft.com/en-us/library/system.io.ports.serialport%28v=vs.110%29.aspx) ? Кроме того, вы ждете, чтобы получить ответ? Было бы хорошо отправить вторую команду раньше, если бы ответ был получен до 500 мс? –