Forum: PC-Programmierung [C#] Variable wird nicht übernommen


von Draco (Gast)


Lesenswert?

Ich habe hier ein Problem, mit welchem ich gerade nicht weiter komme:


Ich habe ein Programm welches mir Daten an einen µC sendet und wieder 
empfängt. Das funktioniert eigentlich auch ganz gut - bis auf den 
Umstand das eine Variable aus dem Receive Handler nicht übernommen wird:

1
//..
2
volatile string varHardwareVersion;                    //Volatile
3
//..
4
5
private void butInfoClick(object sender, EventArgs e)  //Button Event Handler
6
{
7
  FormControllerInfo f = new FormControllerInfo();     //New Form from FormControllerInfo
8
9
  f.mComPort = ComPort.PortName;                       //Variable set 
10
11
  Gauge.mGetHardwareVersion();                         //Set Command to µC
12
  ComSend(Gauge.mByteToSend);                          //Send Command to µC
13
  Gauge.SetupGauge(0x02);                              //Reset µC to default   
14
15
  f.mVersionString = varHardwareVersion;              //!!! Hier Fehler !!!!
16
  this.Text = varHardwareVersion;                     //!!! Hier Fehler !!!! 
17
18
  f.Show();                                            //Show Form
19
}
20
21
22
//... Der Com Port Receive Handler....
23
24
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
25
{
26
   SerialPort sp = (SerialPort)sender;          // ComPort from object sender
27
28
   string indata = sp.ReadLine();               // Get uart data
29
   char[] inchar = indata.ToArray();            // convert to byte array
30
31
   //vol_AppHead(indata);                       // Debug: Work (volatile)
32
            
33
   varHardwareVersion = inchar[0].ToString();  // First byte to string: work
34
   vol_AppHead(varHardwareVersion);             // show value: Work!!
35
36
   switch (inchar[0])
37
   {
38
       case 'x':
39
           break;
40
       case 'v':
41
           break;
42
       case 'V':
43
           //varHardwareVersion = indata;
44
       break;
45
    }
46
}

Soo... also der String wird empfangen und der erste Byte in die Variable 
varHardwareVersion geschrieben (spielt auch keine Rolle ob der indata 
String geschrieben wird, kommt aufs gleiche raus), dann wird sie mir 
über eine geschützte Funktion (vol_AppHead) ausgegeben. Das klappt 
wunderbar.

Nun aber ist die Variable wieder zurück in butInfoClick wieder leer. Da 
wo in den Kommentaren !!!HIER FEHLER!!! steht. Jedoch ist sie doch aber 
volatile geschützt, wieso ist sie denn dann leer wenn sie doch aber 
beschrieben wird und auch angezeigt wird?!

Ich stehe aufm Schlauch :D

von Peter II (Gast)


Lesenswert?

volatile ist doch kein Schutz!

Eventuell kommt ja schon die nächste Nachricht an und setzt die Variable 
auf einen neue Wert. DataReceivedHandler ist ja Asynchron.

Außerdem ist sp.ReadLine(); im DataReceivedHandler keine Gute Idee, dort 
sollte man nur das lesen was auch da ist und nicht warten.

von Draco (Gast)


Lesenswert?

Na in dem Sinne geschützt das Threadübergreifend darauf zugegriffen 
werden kann. Aber die Variable wird ausschlaußlich an diesen beiden 
Stellen genutzt.

Hmmm... du meinst quasi das der Programmcode weiter ausgeführt wird in 
butInfoClick, die Variable da noch garnicht gesetzt ist wenn sie 
übergeben wird. Und der ReceiveHandler erst später "zuschlägt"?!

Da muss ich mir was einfallen lassen das butInfoClick erst weitermacht 
wenn varHardwareVersion gesetzt ist.

von Peter II (Gast)


Lesenswert?

Draco schrieb:
> Hmmm... du meinst quasi das der Programmcode weiter ausgeführt wird in
> butInfoClick, die Variable da noch garnicht gesetzt ist wenn sie
> übergeben wird. Und der ReceiveHandler erst später "zuschlägt"?!

ja, du wartest doch nirgends.


Du könntest das ganze ohne Event machen, einfach in butInfoClick den 
comport mit readline lesen. Dann blockiert aber dein Programm, wenn 
niemand antwortet.

von Draco (Gast)


Lesenswert?

Sooo....


ich habe mal, auf deinen Ratschlag hin, das sp.ReadLine() zu 
sp.ReadExisting() geändert.

Die butInfoClick hab ich nun um eine While Schleife ergänzt die solange 
läuft wie varHardwareVersion == "" ist. Das funktioniert nun. Ich muss 
nun nur noch ne Abbruchbedingung aus der Schleife machen, sollte nach 
einer gewissen Zeit keine Daten ankommen.

Interessant wäre auch, die ComPort direkt nach dem Senden auszulesen. 
Aber da kommt mir ja der ReceiveHandler dazwischen bzw kollidieren sie 
sich ja. Kann ich während des Programmablaufes den Eventhandler 
"wegnehmen"?
1
ComPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

von Draco (Gast)


Lesenswert?

Peter II schrieb:
> Du könntest das ganze ohne Event machen, einfach in butInfoClick den
> comport mit readline lesen. Dann blockiert aber dein Programm, wenn
> niemand antwortet.

Naja zumindest nur solange wie Timeout in ComPort gesetzt ist, solange 
darf das warten und das Programm stillstehen :D

von Peter II (Gast)


Lesenswert?

Draco schrieb:
> Interessant wäre auch, die ComPort direkt nach dem Senden auszulesen.
> Aber da kommt mir ja der ReceiveHandler dazwischen bzw kollidieren sie
> sich ja. Kann ich während des Programmablaufes den Eventhandler
> "wegnehmen"?

ja sollte gehen, aber warum setzt du ihn überhaupt?

von Draco (Gast)


Lesenswert?

Peter II schrieb:
> ja sollte gehen, aber warum setzt du ihn überhaupt?

Weil ich von dem µC immer "Pings" bekomme (Case x im Eventhandler). Der 
Code ist aber rausgeflogen für hier.

Ich habe nun die butInfoClick angepasst um die Daten dann direkt zu 
lesen. Klappt nun wunderbar. Ich danke dir ganz doll!

[c]

private void butInfoClick(object sender, EventArgs e)
{
   ComPort.DataReceived -= DataReceivedHandler;      //Remove 
EventHandler

   FormControllerInfo f = new FormControllerInfo();
   f.mComPort = ComPort.PortName;

   Gauge.mGetHardwareVersion();
   ComSend(Gauge.mByteToSend);
   Gauge.SetupGauge(0x02);

   try                                                 //Catch Timout
   {
     varHardwareVersion = ComPort.ReadLine();          //ReadLine
   }
   catch
   {
     varHardwareVersion = "Error reading Port";
   }

   ComPort.DataReceived += new 
SerialDataReceivedEventHandler(DataReceivedHandler);  //Set EventHandler

   f.mVersionString = varHardwareVersion;
   f.Show();
}

von Draco (Gast)


Lesenswert?

Peter II schrieb:
> ja sollte gehen, aber warum setzt du ihn überhaupt?

Weil ich von dem µC immer "Pings" bekomme (Case x im Eventhandler). Der 
Code ist aber rausgeflogen für hier.

Ich habe nun die butInfoClick angepasst um die Daten dann direkt zu 
lesen. Klappt nun wunderbar. Ich danke dir ganz doll!
1
private void butInfoClick(object sender, EventArgs e)
2
{
3
   ComPort.DataReceived -= DataReceivedHandler;      //Remove EventHandler
4
            
5
   FormControllerInfo f = new FormControllerInfo();
6
   f.mComPort = ComPort.PortName;
7
8
   Gauge.mGetHardwareVersion();
9
   ComSend(Gauge.mByteToSend);
10
   Gauge.SetupGauge(0x02);
11
12
   try                                                 //Catch Timout
13
   {
14
     varHardwareVersion = ComPort.ReadLine();          //ReadLine
15
   }
16
   catch
17
   {
18
     varHardwareVersion = "Error reading Port";
19
   }
20
21
   ComPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);  //Set EventHandler
22
23
   f.mVersionString = varHardwareVersion;
24
   f.Show();
25
}

EDIT.... Waaahhh falscher Knopf! :D

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.