2010-12-29 4 views
-1

Это мой первый проект C#, поэтому я могу делать что-то явно неправильное в коде ниже. Я использую .NET, WinForms (я думаю), и это настольное приложение, пока я не получу ошибки. UpdateGui() использует Invoke((MethodInvoker)delegate для обновления различных элементов управления графическим интерфейсом на основе принятых последовательных данных, а отправляет команду GetStatus() из последовательного порта 4 раза в секунду. Тема Read() считывает ответ от последовательного порта, когда он прибывает, который должен быть близок к немедленному. SerialPortFixer is SerialPortIOException Обход проблемы в 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?

Что касается таймера обновления, то существует special purpose windows forms timer, который периодически запускается, что не требует использования Invoke. Это правильный инструмент для работы

+0

serialport1 не становится null. Кажется, что выход происходит в потоке таймера, который вызывает UpdateGui. Таймер запускает UpdateGui 4 раза в секунду, но в конечном итоге умирает. В UpdateGui гораздо больше, чем показано, возможно, это stackoverflow. Должен ли вывод отладки отображать исключение stackoverflow? Используется ли метод MethodInvoker в этой периодической задаче плохая идея? – jacknad

+0

Спасибо миллиону Исаку. Окно формирует таймер, прибивая его. – jacknad

Смежные вопросы