2015-07-21 3 views
1

Часть программы, которую я модифицирую, включает в себя передачу через последовательный порт с использованием запатентованной библиотеки. К сожалению, эта библиотека не имеет того же SerialPort.DataReceived event, что и пространство имен System.IO.Ports. На самом деле, он не имеет никаких событий вообще, однако у него есть две функции, которые, вероятно, могут быть использованы аналогичным образом:Поднять событие при возврате функции True

  1. Port.WaitForData (интермедиат время)

    Эта функция ждет определенное количество времени, чтобы получать некоторые ранее указанные строки над портом. Он возвращает 1 для да, полученная строка, или 0 для нет, не получил строку, тайм-аут.

  2. Port.IsReceiveBufferEmpty()

    Эта функция возвращает логическое значение из да, приемный буфер пуст или нет, приемный буфер содержит данные.

Мне кажется, я должен создать некоторую нить непрерывно зацикливание при открытии порта и сделать одну из этих двух вещей:

  1. Для каждого цикла, называют WaitForData (некоторые большое количество) с указанными строками, которые он ищет для «», или vbCrLf, или что-то еще, что я могу подтвердить, будет получать каждый раз, когда отправляются данные. Если он находит что-то, прочитайте его и напишите в текстовое поле. Если WaitForData ничего не найдет, повторите цикл.

  2. Для каждого цикла вызовите IsReceiveBufferEmpty(), а если нет, прочитайте его и напишите в текстовое поле.

Какой лучший способ реализовать это? Первые варианты кажутся потенциально более эффективными для меня, хотя я почти ничего не знаю о том, как этот метод работает под капотом. Очевидно, что я хочу, чтобы моя форма реагировала на это, так как я должен продолжать непрерывный цикл, не замораживая форму, но имея возможность читать любые входящие данные?

Благодарим за помощь.

+0

Написание такого API для общего использования будет отличаться от его оптимизации для любого приложения, которое вы пишете. мы ничего не знаем о вашем приложении. одна вещь: «... писать в текстовое поле ...», вы будете иметь возможность сделать это из любого рода потокового решения. Я бы поднял событие и предоставил полученные данные, и пусть потребитель справится с ним. – Plutonix

+0

@Plutonix Я не совсем уверен, как имитировать событие DataReceived в моем коде, и я пытаюсь найти лучший способ сделать это. Приложение принимает входные данные из текстового поля, отправляет его на порт, а затем считывает что-либо обратно из порта. Есть ли больше информации, которая вам нужна, чтобы в целом описать, как можно было бы это сделать? Могут ли мои решения выше иметь смысл? Кроме того, в многопоточных приложениях я могу использовать Invoke или что-то похожее на запись в компоненты формы, правильно? – Django

+0

Можете ли вы использовать 'Async/Await' (VS 2012+/.NET 4.5+ - или 4.0 с некоторыми дополнительными библиотеками)? – Mark

ответ

1

Возможно, это не самое элегантное решение, но вы можете использовать BackgroundWorker для ввода IO. например что-то вроде этого псевдокода:

Public Class MyForm 

    Private _port As ProprietaryIOLibrary 
    Private WithEvents Worker As System.ComponentModel.BackgroundWorker 

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load 
     _port = New ProprietaryIOLibrary() 
     Worker = New System.ComponentModel.BackgroundWorker() 
     Worker.WorkerReportsProgress = True 
     Worker.WorkerSupportsCancellation = True 
     Worker.RunWorkerAsync() 
    End Sub 

    Private Sub ButtonCancel_Click(sender As Object, e As EventArgs) Handles ButtonCancel.Click 
     Worker.CancelAsync() 
    End Sub 

    Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork 
     Do 
      If _port.WaitForData(1000) Then ' Adjust timeout depending on cancel responsiveness? 
       Dim data As String = _port.ReadDataAsString() ' ? 
       ' Trigger the ProgressChanged event, passing the data 
       Worker.ReportProgress(0, data) 
      End If 
      If Worker.CancellationPending Then 
       Exit Do 
      End If 
     Loop 
    End Sub 

    Private Sub Worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Worker.ProgressChanged 
     ' Update the UI with the data received 
     ' ProgressChanged is called on the UI thread, so no need to Invoke 
     Dim data As String = DirectCast(e.UserState, String) 
     TextBox1.Text &= data & vbCrLf 
    End Sub 

    Private Sub Worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles Worker.RunWorkerCompleted 
     TextBox1.Text &= "Complete!" 
    End Sub 

End Class 
Смежные вопросы