2010-12-29 7 views
-1

これは私の最初のC#プロジェクトですので、以下のコードで明らかに不適切なことを行っている可能性があります。 私は.NET、WinForms(私は思う)を使用しています。これはバグを出すまではデスクトップアプリケーションです。 UpdateGui()Invoke((MethodInvoker)delegateを使用して、受信したシリアルデータに基づいてさまざまなGUIコントロールを更新し、 はGetStatus()コマンドをシリアルポートから1秒間に4回送信します。 スレッドRead()は、到着するたびにシリアルポートから応答を読み取ります。 SerialPortFixerSerialPortIOExceptionです。C#の回避策は、 http://zachsaw.blogspot.com/2010/07/serialport-ioexception-workaround-in-c.htmlです。なぜC#スレッドが死んでいるのですか?

いずれかまたは両方のスレッドが終了した後、 The thread 0x1288 has exited with code 0 (0x0)のようなものが表示されます。デバッグコードの出力に

なぜUpdateGui()および/またはRead()は最終的に死ぬのですか?あなたがスレッドのリターンを作成するときの方法は、指定したときに、より具体的に実行、またはするこれ以上のコードがないとき

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

あなたのためにあなたのプログラムをデバッグすることを真剣におねがいしますか? –

+0

いいえ、私は数日間それをハッキングしていました。おそらく、私はC#に詳しい方には明らかないくつかの練習に違反しています。 – jacknad

+0

スレッド終了メッセージがいずれかのスレッドに関連付けられていると仮定しているのはなぜですか? –

答えて

4

スレッドが終了します。

serialport1がnullになることはありますか?

更新タイマーはで、定期的に実行されるため、Invokeを使用する必要はありません。それは仕事のための適切なツールです

+0

serialport1はnullになりません。 ExitはUpdateGuiを呼び出すタイマースレッドで起きているようです。タイマーはUpdateGuiを1秒に4回実行しますが、最終的には終了します。 UpdateGuiには表示されているものより多くのものがありますが、おそらくそれはスタックオーバーフローです。デバッグ出力は、stackoverflow例外を表示する必要がありますか?この定期的なタスクでMethodInvokerを使用するのは悪い考えですか? – jacknad

+0

ありがとうございます。窓はそれを釘付けにするタイマーを形成する。 – jacknad