Ich weiß nicht genau ob ich hier wirklich 2 Threads brauche.
Zum besseren Verständnis... ich weiß nicht wirklich wie lange die jetzt dafür brauchen....
Form1 sendet Daten über den IO-Port an ein Gerät
Dort werden die Daten verarbeitet und dann zurückgesendet.
Bei empfang von Daten des IO-Ports in der Form1, werden die Daten ausgewertet und in einer Picturebox angezeigt, bzw. in eine Textbox geschrieben
Angenommen ich sende an den IO-Port Daten und zwar 1175 mal. Das ganze würde z.B. 20 sekunden dauern.
Das externe Gerät empfängt die Daten und sendet schon nach erhalt des ersten Datensatz, also nach 3 sekunden zurück.
Aber auf der Gui wird erst nach 20 sekunden etwas in die picturebox, bzw. textbox geschrieben. Sprich 17 sekunden lang haben die Daten darauf gewartet, bis die Gui mit dem senden fertig war und sich um die empfangen Daten kümmern kann.
Problem kurz:
Form1 -> senden Daten 1
Form1 -> senden Daten 2
// etc.
Form1 -> senden Daten 1175
Form1 <- empfangene Daten1 verarbeiten
Form1 <- empfangene Daten2 verarbeiten
//etc.
Form1 <- empfangene Daten1175 verarbeiten
ich hätte aber gerne, das das senden ünterbrochen wird, sobald daten ankommen und sich darum gekümmert wird. Also eine höhere Priorität haben. Am besten so...
(Geht das nur mit threads? oder gibt es da eine kurz elegante Lösung. Denn Threads habe ich mir schon durchgelesen, aber finde ich doch schwer zu begreifen wie ich das auf mein Problem anwenden könnte.)
Form1 -> senden Daten 1
Form1 <- empfangene Daten1 verarbeiten
Form1 -> senden Daten 2
Form1 <- empfangene Daten2 verarbeiten
Form1 -> senden Daten 3
Form1 <- empfangene Daten3 verarbeiten
// etc.
Form1 -> senden Daten 1175
Form1 <- empfangene Daten1175 verarbeiten
private void bnMouseClick_Click(object sender, EventArgs e)
{
uhr.Start();
// erst wenn die schleife komplett durchgelaufen ist und bnMouseClick_Click verlassen wurde
// springt der Code in Empfangen rein und verarbeitet die angekommenen Daten und nicht schon sobald
// die Daten ankommen
for (int i = 1; i < 1175; i++)
{
txtReceive.AppendText("\r\n");
RGB = (bbc[i, 9] + "#" + bbc[i, 10] + "#" + bbc[i, 11]);
TimeSpan zeit = uhr.Elapsed;
double zeitneu = zeit.TotalMilliseconds;
if ((zeitneu - zeitalt) >= 80) // erst senden, wenn 80 millisekunden seit dem letzten senden vergangen sind
{
Senden(); // Senden an IO Port
}
else
{
i=i-1;
}
}
txtReceive.AppendText("\r\n ende");
uhr.Stop();
}
private void Senden()
{
try
{
if (RGB.Length > 0)
{
Arduino.Write(RGB); //senden an den IO Port
txtReceive.AppendText("\r\n <<<<: " + rgb[0] + " # " + rgb[1] + " # " + rgb[2]);
ScollToBottom();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK);
}
}
private void Empfangen(object sender, SerialDataReceivedEventArgs e)
{
try
{
RGB = Arduino.ReadLine(); // empfangen vom IO port
Berechnung_rgb_xy(); // Daten verarbeiten und in picturebox1 anzeigen
this.Invoke(new EventHandler(Empfangen_event));
}
catch
{
MessageBox.Show("Error Serial Event Handler, cannot listen for data", "Error", MessageBoxButtons.OK);
}
}
private void Empfangen_event(object sender, EventArgs e)
{
txtReceive.AppendText("\r\n xyz back :" + xyz[0] + " # " + xyz[1] + " # " + xyz[2]);
txtReceive.AppendText("\r\n----------------------------------------------------------------------------------------------");
}
ScollToBottom();
}
Du brauchst das Senden nicht unterbrechen, wenn du das Senden in einem Task erledigst. Dann hat die GUI auch Zeit die ankommenden Nachrichten zu empfangen.
Die Thread
-Klasse sollte man heutzutage wirklich nur noch nutzen, wenn es unbedingt erforderlich ist.
Viel einfacher für den Entwickler sind Tasks
, die im Prinzip den gleichen Effekt haben; nämlich Nebenläufigkeit.
Im Prinzip kannst Du das sehr einfach mit einer Queue abarbeiten.
Du hast SendJobs und ReceiveJobs, wobei die Queue nach ReceiveJobs sortiert/priorisiert sind, sodass diese in der Queue stets zuerst abgearbeitet werden.
Dazu gibt es auch den Priority Queue Pattern.
Der Sinn dieser Priorisierung ist mir aber nicht ersichtlich.
Warum nicht die gesamte Kommunikation in Tasks auslagern.. so würde man das eigentlich machen.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Kann hier abt nur Recht geben. Die gescheite Vorgehensweise ist:
a) Du nutzt den ohnehin vorhandenen Task einzig für deine UI, damit die niemals hängt
b) Wenn du sendest/empfängst nutzt du je einen entsprechenden Task
Mit der Vorgehensweise brauchst du nichts zu priorisieren und alles würde flüssig durch laufen.
LG
Problem 1:
Hmm soweit klappt das zwar jetzt. Aber alles was in meinem gestartetem Task läuft kann ja wiederrum nicht auf Textboxen der GUI zugreifen.
Wenn ich es mit this.invoke versuche, klappt das leider auch nicht.
Problem 2:
Dadurch das senden und empfangen jetzt in eigenen tasks laufen kann ich das gesendete RGBh mit dem empfangenen RGBz nicht mehr vergleichen, weil zu dem zeitpunkt, wenn ich RGBz empfange, die daten in RGBh schon evtl. wieder überschrieben wurden. (nicht immer aber manchmal)
private void bnMouseClick_Click(object sender, EventArgs e)
{
Task bbcSenden = new Task(new Action(BlackBodyCurve));
bbcSenden.Start();
}
private void BlackBodyCurve()
{
uhr.Start();
// erst wenn die schleife komplett durchgelaufen ist und bnMouseClick_Click verlassen wurde
// springt der Code in Empfangen rein und verarbeitet die angekommenen Daten und nicht schon sobald
// die Daten ankommen
for (int i = 1; i < 1175; i++)
{
txtReceive.AppendText("\r\n"); //Fehler
RGBh = (bbc[i, 9] + "#" + bbc[i, 10] + "#" + bbc[i, 11]);
TimeSpan zeit = uhr.Elapsed;
double zeitneu = zeit.TotalMilliseconds;
if ((zeitneu - zeitalt) >= 80) // erst senden, wenn 80 millisekunden seit dem letzten senden vergangen sind
{
Senden(); // Senden an IO Port
}
else
{
i=i-1;
}
}
txtReceive.AppendText("\r\n ende"); // Fehler
uhr.Stop();
}
private void Senden()
{
try
{
if (RGBh.Length > 0)
{
Arduino.Write(RGBh); //senden an den IO Port
// txtReceive.AppendText("\r\n <<<<: " + rgb[0] + " # " + rgb[1] + " # " + rgb[2]);
ScollToBottom();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK);
}
}
private void Empfangen(object sender, SerialDataReceivedEventArgs e)
{
try
{
RGBz = Arduino.ReadLine(); // empfangen vom IO port
Berechnung_rgb_xy(); // Daten verarbeiten und in picturebox1 anzeigen
this.Invoke(new EventHandler(Empfangen_event));
}
catch
{
MessageBox.Show("Error Serial Event Handler, cannot listen for data", "Error", MessageBoxButtons.OK);
}
}
private void Empfangen_event(object sender, EventArgs e)
{
txtReceive.AppendText("\r\n xyz back :" + xyz[0] + " # " + xyz[1] + " # " + xyz[2]);
txtReceive.AppendText("\r\n----------------------------------------------------------------------------------------------");
}
ScollToBottom();
}
@Abt: ich verstehe was du meinst und ja bräuchte man eigentlich nicht, aber wie löse ich jetzt mein Problen nr. 2?
Ich hab ehrlich gesagt nicht so wirklich den Einblick, was Du überhaupt bauen willst.
Daher ist es auch nicht einfach, Dir zu helfen, weil offensichtlich nach und nach mehr Anforderungen hier bekannt werden.
Erzähl doch mal, was Du vor hast, bevor wir Dir jetz noch 2-3 Vorschläge bringen, die dann neue Probleme schaffen und wir unnötig Zeit investieren.
=)
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code