Nehmen wir an, ich möchte eine Funktion haben, die Daten aus dem SerialPort liest und ein Byte [] zurückgibt.Offensichtlich ist dies nicht die richtige Art zu lesen mit SerialPort
public byte[] RequestData(byte[] data)
{
//See code below
}
Etwas so einfach wie das wirklich nicht/ausführen funktioniert gut und ist nicht sehr zuverlässig:
byte[] response = new byte[port.ReadBufferSize];
port.Open();
port.Write(data, 0, data.Length);
Thread.Sleep(300); //Without this it doesn't even work at all
Console.WriteLine("Bytes to read: {0}", port.BytesToRead);
int count = port.Read(response, 0, port.ReadBufferSize);
Console.WriteLine("Read {0} bytes", count);
port.Close();
port.Dispose();
return response.GetSubByteArray(0, count);
Ich habe auch versucht die Thread.Sleep mit etwas zu ersetzen, wie:
while (port.BytesToRead < 14)
{
//Maybe Thread.Sleep(10) here?
}
Aber das verursacht Probleme. (PS: Ich weiß, ich brauche mindestens 14 Bytes)
Natürlich ist eine bessere Art und Weise (glaube ich), wie etwas zu haben wäre:
port.ReceivedBytesThreshold = 14;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
port.Write(data, 0, data.Length);
Und dann einen Handler natürlich mit:
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var port = (SerialPort)sender;
while (port.BytesToRead > 0)
{
//Read the data here
}
}
Aber dann kann ich die Daten nicht als Ergebnis der Funktion, die ich definieren wollte, zurückgeben? Der Clientcode, der dies verwendet, müsste ein Ereignis abonnieren, das durch diesen Code ausgelöst wird, , aber wie würde es dann wissen, dass die Antwort wirklich die Antwort auf die Anfrage ist, die es gerade gemacht hat.
(Mehrere Nachrichten können gesendet werden, und ich kann mir vorstellen, dass eine Nachricht länger auf der anderen Seite verarbeitet als die andere oder etwas). richtig
würde Jede beraten
UPDATE
Der folgende Code funktioniert viel besser, willkommen sein, aber wenn ich die Thread.Sleep() Aussagen entfernen stoppt es wieder zu arbeiten. Zum Beispiel zeigt das Überwachungstool für serielle Schnittstellen deutlich an, dass 17 Bytes in die serielle Leitung geschrieben wurden. Das erste Mal BytesToRead = 10 und das nächste Mal BytesToRead = 4, aber dann bleibt BytesToRead 0, also wohin sind die letzten 3 Bytes gegangen?
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100);
while (port.BytesToRead > 0)
{
Console.WriteLine("Bytes to read: {0}", port.BytesToRead);
var count = port.BytesToRead;
byte[] buffer = new byte[count];
var read = port.Read(buffer, 0, count);
if (count != read)
Console.WriteLine("Count <> Read : {0} {1}", count, read);
var collectAction = new Action(() =>
{
var response = dataCollector.Collect(buffer);
if (response != null)
{
this.OnDataReceived(response);
}
});
collectAction.BeginInvoke(null, null);
Thread.Sleep(100);
}
}
Dies ist immer noch sehr viel _nicht_ die Art, einen SerialPort zu lesen. –
Dann was ist, weil es wirklich jetzt funktioniert – TimothyP
Nur ein heads-up für jeden, der dies liest: Das DataReceived-Ereignis wird in einem anderen Thread ausgelöst als derjenige, der die SerialPort-Instanz erstellt hat. Siehe http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx – rkagerer