2010-12-29 15 views
-1

Dies ist mein erstes C# -Projekt, also kann ich etwas offensichtlich Unpassendes im Code unten tun. Ich benutze. NET, WinForms (denke ich), und das ist eine Desktop-Anwendung, bis ich die Fehler raus. UpdateGui() verwendet Invoke((MethodInvoker)delegate, um verschiedene GUI-Steuerungen basierend auf empfangenen seriellen Daten zu aktualisieren, und sendet einen GetStatus() Befehl über den seriellen Anschluss 4 Mal pro Sekunde. Thread Read() liest die Antwort von der seriellen Schnittstelle, wenn es ankommt, die in der Nähe sofort sein sollte. SerialPortFixer ist ein SerialPortIOException Workaround in C# Ich fand bei http://zachsaw.blogspot.com/2010/07/serialport-ioexception-workaround-in-c.html.Warum stirbt C# Gewinde?

Nach einem oder beiden Fäden sterben sehe ich etwas wie The thread 0x1288 has exited with code 0 (0x0). in der Debug-Code-Ausgabe.

Warum verschwinden UpdateGui() und/oder Read() irgendwann?

public partial class UpdateStatus : Form 
{ 
    private readonly byte[] Command = new byte[32]; 
    private readonly byte[] Status = new byte[32]; 
    readonly Thread readThread; 
    private static readonly Mutex commandMutex = new Mutex(); 
    private static readonly Mutex statusMutex = new Mutex(); 
    ... 

    public UpdateStatus() 
    { 
     InitializeComponent(); 
     SerialPortFixer.Execute("COM2"); 
     if (serialPort1.IsOpen) 
     { 
      serialPort1.Close(); 
     } 
     try 
     { 
      serialPort1.Open(); 
     } 
     catch (Exception e) 
     { 
      labelWarning.Text = LOST_COMMUNICATIONS + e; 
      labelStatus.Text = LOST_COMMUNICATIONS + e; 
      labelWarning.Visible = true; 
     } 
     readThread = new Thread(Read); 
     readThread.Start(); 
     new Timer(UpdateGui, null, 0, 250); 
    } 
    static void ProcessStatus(byte[] status) 
    { 
     Status.State = (State) status[4]; 
     Status.Speed = status[6]; // MSB 
     Status.Speed *= 256; 
     Status.Speed += status[5]; 
     var Speed = Status.Speed/GEAR_RATIO; 
     Status.Speed = (int) Speed; 
     ... 
    } 
    public void Read() 
    { 
     while (serialPort1 != null) 
     { 
      try 
      { 
       serialPort1.Read(Status, 0, 1); 
       if (Status[0] != StartCharacter[0]) continue; 
       serialPort1.Read(Status, 1, 1); 
       if (Status[1] != StartCharacter[1]) continue; 
       serialPort1.Read(Status, 2, 1); 
       if (Status[2] != (int)Command.GetStatus) continue; 
       serialPort1.Read(Status, 3, 1); 
       ... 
       statusMutex.WaitOne(); 
       ProcessStatus(Status); 
       Status.update = true; 
       statusMutex.ReleaseMutex(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(@"ERROR! Read() " + e); 
      } 
     } 
    } 
    public void GetStatus() 
    { 
     const int parameterLength = 0; // For GetStatus 
     statusMutex.WaitOne(); 
     Status.update = false; 
     statusMutex.ReleaseMutex(); 
     commandMutex.WaitOne(); 
     if (!SendCommand(Command.GetStatus, parameterLength)) 
     { 
      Console.WriteLine(@"ERROR! SendCommand(GetStatus)"); 
     } 
     commandMutex.ReleaseMutex(); 
    } 
    private void UpdateGui(object x) 
    { 
     try 
     {     
      Invoke((MethodInvoker)delegate 
      { 
       Text = DateTime.Now.ToLongTimeString(); 
       statusMutex.WaitOne(); 
       if (Status.update) 
       { 
        if (Status.Speed > progressBarSpeed.Maximum) 
        { 
         Status.Speed = progressBarSpeed.Maximum; 
        } 
        progressBarSpeed.Value = Status.Speed; 
        labelSpeed.Text = Status.Speed + RPM; 
        ... 
       } 
       else 
       { 
        labelWarning.Text = LOST_COMMUNICATIONS; 
        labelStatus.Text = LOST_COMMUNICATIONS; 
        labelWarning.Visible = true; 
       } 
       statusMutex.ReleaseMutex(); 
       GetStatus(); 
      }); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(@"ERROR! UpdateGui() " + e); 
     } 
    } 
} 
+1

Sie bitten uns ernsthaft, Ihr Programm für Sie zu debuggen? –

+0

Nein. Ich habe es ein paar Tage lang gehackt. Vielleicht verstoße ich gegen etwas, das für diejenigen, die mit C# vertrauter sind, offensichtlich ist. – jacknad

+0

Warum gehen Sie davon aus, dass die Thread-Exit-Nachricht einem der Threads zugeordnet ist? –

Antwort

4

Ein Thread wird beendet, wenn es nicht mehr Code ist auszuführen, oder genauer gesagt, wenn die Methode, die Sie angeben, wenn Sie Thread kehrt erstellen.

Vielleicht serialport1 wird Null?

Für den Aktualisierungstimer gibt es einen special purpose windows forms timer, der regelmäßig ausgeführt wird, so dass Sie Invoke nicht verwenden müssen. Es ist das richtige Werkzeug für den Job

+0

serialport1 wird nicht null. Der Exit scheint im Timer-Thread zu passieren, der UpdateGui aufruft. Der Timer führt 4 Mal pro Sekunde UpdateGui aus, stirbt aber irgendwann. Es gibt viel mehr in UpdateGui als gezeigt, vielleicht ist es ein Stackoverflow. Sollte die Debug-Ausgabe eine Stapelüberlauf-Ausnahme anzeigen? Ist die Verwendung von MethodInvoker in dieser periodischen Aufgabe eine schlechte Idee? – jacknad

+0

Danke eine Million Isak. Der Windows Forms Timer hat es genagelt. – jacknad