Почему поток C # умирает? - PullRequest
       2

Почему поток C # умирает?

0 голосов
/ 29 декабря 2010

Это мой первый проект на C #, поэтому я могу делать что-то явно неправильное в приведенном ниже коде.Я использую .NET, WinForms (я думаю), и это настольное приложение, пока я не получу ошибки.UpdateGui() использует Invoke((MethodInvoker)delegate для обновления различных элементов управления графическим интерфейсом на основе полученных последовательных данных и отправляет команду GetStatus() через последовательный порт 4 раза в секунду.Поток Read() читает ответ от последовательного порта всякий раз, когда он прибывает, который должен быть почти немедленным.SerialPortFixer - это SerialPort IOException Обходной путь в C # Я нашел в http://zachsaw.blogspot.com/2010/07/serialport-ioexception-workaround-in-c.html.

После того, как один или оба потока умрут, я увижу что-то вроде 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 Ответ

4 голосов
/ 29 декабря 2010

Поток завершится, когда больше не будет кода для выполнения, или, более конкретно, когда метод, указанный вами при создании потока, вернется.

Может быть, serialport1 станет нулевым?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...