为什么C#thread死了?

时间:2010-12-29 19:47:04

标签: c# winforms multithreading

这是我的第一个C#项目,所以我可能会在下面的代码中做一些明显不合适的事情。 我正在使用.NET,WinForms(我认为),这是一个桌面应用程序,直到我收到错误。 UpdateGui()使用Invoke((MethodInvoker)delegate根据收到的串行数据更新各种GUI控件 每秒4次从串口发送GetStatus()命令。 线程Read()在到达时应该从串口读取应该立即接近的响应。 SerialPortFixer是我发现的C#中的SerialPort IOException解决方法 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 个答案:

答案 0 :(得分:4)

当没有更多代码要执行时,或者更具体地说,当您创建线程返回时指定的方法时,线程将终止。

也许serialport1变为空?

对于更新计时器,有一个special purpose windows forms timer定期运行,不需要您使用Invoke。这是工作的正确工具