崇文殿大学士 2020-04-21 09:43 采纳率: 0%
浏览 317
已结题

C# 讀串口為何Timer會死掉

讀串口的程序死掉,有打計數器,計數器在20-30分鐘不等會停止跳動。

一開始懷疑是GC回收了Timer,使用了保活,不行;
後來懷疑系統回收了中間變量,使用了微軟的TryStartNoGCRegion,
不行;
不接串口時,計數器單獨放一個晚上都沒事;
串口使用C語言讀取,2個小時沒事。

讀串口的部分查閱了微軟標準的寫法,讀寫的buffer每次都是有清除的。

請大神指點,放久了,為何Timer計數會死掉。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using MES.Util;
using System.Runtime;

namespace MES.Operation
{

    public partial class Suckion : Form
    {
        [System.Security.SecurityCritical]
        public static bool TryStartNoGCRegion;

        public static SerialPort serialPort = null;
        public Suckion()
        {
            InitializeComponent();
        }
        public static string[] SerialPortNames
        {
            get
            {
                string[] serialports = SerialPort.GetPortNames();
                Array.Sort(serialports, new Comparison<string>(
                    delegate (string x, string y)
                    {
                        if (x.Length > 3 && y.Length > 3)
                        {
                            string index1 = x.Substring(3);
                            string index2 = y.Substring(3);
                            try
                            {
                                int n1 = Convert.ToInt32(index1);
                                int n2 = Convert.ToInt32(index2);
                                return n1 - n2;
                            }
                            catch
                            {
                            }
                        }
                        return 0;
                    }));
                return serialports;
            }
        }
        System.Timers.Timer t = new System.Timers.Timer(1500);
        private void Suckion_Load(object sender, EventArgs e)
        {
            //comboBox1.Items.AddRange(SerialPortNames);
            //comboBox1.SelectedIndex = 0;

            label5.Text = Util.PublicVar.UserID;
            label3.Text = Util.PublicVar.Line;

            //打開串口
            serialPort = new SerialPort();
            serialPort.PortName = "COM1";
            serialPort.BaudRate = Convert.ToInt32(9600);
            serialPort.Parity = Parity.None;
            serialPort.DataBits = Convert.ToInt32(8);
            serialPort.StopBits = StopBits.One;
            serialPort.Handshake = Handshake.None;
            serialPort.WriteTimeout = 200;
            serialPort.ReadTimeout = 200;

            if (serialPort.IsOpen == false)
            {
                serialPort.Open();
            }

            Query();

            //異步線程定時器

            t.Elapsed += new System.Timers.ElapsedEventHandler(GetSuctionValue);//到达时间的时候执行事件;
            t.AutoReset = true;//设置是执行一次(false)还是一直执行(true);
            t.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件;

            //GC.KeepAlive(t);
        }

        private void Query()
        {
            string sql = @"SELECT TOP 50
                           bi.Line 產線
                           ,bi.Main 主機
                           ,bi.SuctionValue 吸力
                           ,case when bi.SuctionValue is null then '' when bi.SuctionValue<-7 and bi.SuctionValue>-15 then 'OK'
                                 else 'NG' end 判定結果
                           ,CONVERT(varchar(100), bi.SuctionTime, 20)  吸力上傳時間
                           FROM dbo.BindingInfo bi WHERE bi.Line='" + Util.PublicVar.Line + "' and bi.SuctionTime is not null ORDER BY bi.SuctionTime desc";
            dataGridView1.DataSource = Util.SQLHelper.GetDataTable(sql);
            for (int i = 0; i < dataGridView1.RowCount; i++)
            {
                if (dataGridView1.Rows[i].Cells["判定結果"].Value.ToString() == "NG")
                {
                    dataGridView1.Rows[i].DefaultCellStyle.ForeColor = Color.Red;
                }
            }
        }
        void GetSuctionValue(object source, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                this.BeginInvoke(new TextOption(F));//invok 委托实现跨线程的调用
                GC.KeepAlive(t);
            }
            catch(Exception ex)
            {
                File.AppendAllText(@"C:/Test.txt",ex.ToString());
            }
        }
        delegate void TextOption();//定义一个委托
        private void F()
        {
            try
            {
                label8.Text = (int.Parse(label8.Text) + 1).ToString();
                serialPort.DiscardInBuffer();
                byte[] b = new byte[] { 01, 03, 00, 00, 00, 02, 0xC4, 0x0B };
                serialPort.Write(b, 0, 8);
            }
            catch (Exception)
            {
            }
            SerialPort sp = serialPort;
            sp.DataReceived += new SerialDataReceivedEventHandler(Com_DataReceived);
        }
        private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //开辟接收缓冲区
            byte[] ReDatas = new byte[serialPort.BytesToRead];
            //从串口读取数据
            serialPort.Read(ReDatas, 0, ReDatas.Length);
            //实现数据的解码与显示
            AddData(ReDatas);
            serialPort.DiscardOutBuffer();
        }

        /// <summary>
        /// 解码过程
        /// </summary>
        /// <param name="data">串口通信的数据编码方式因串口而异,需要查询串口相关信息以获取</param>
        public void AddData(byte[] data)
        {
            Thread.Sleep(1000);
            if (data.Length != 9)
            {
                return;
            }
            if (data[0].ToString() != "1")
            {
                return;
            }
            StringBuilder sb = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            byte[] b2 = new byte[4];

            sb.Clear();
            sb.AppendFormat("{0:x2}", data[3]);
            sb.AppendFormat("{0:x2}", data[4]);

            uint num = uint.Parse(sb.ToString(), System.Globalization.NumberStyles.AllowHexSpecifier);
            byte[] floatValue = BitConverter.GetBytes(num);

            int value = BitConverter.ToInt16(floatValue,0);
            try
            {
                  label2.BeginInvoke(new Action(
                    () =>
                    {
                        if (value.ToString().Length < 5)
                        {
                            label2.Text = ((value * 0.1).ToString("0.0"));
                        }
                    }
                    )
                    );
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                throw;
            }
        }
        private void ResultDisplay(string ResultString, Color color)
        {
            if (Result_1.Visible == true && Result_2.Visible == true)
            {
                Result_1.Text = ResultString;
                Result_1.ForeColor = color;
                Result_2.Visible = false;
                Result_2.Text = "";
            }
            else if (Result_1.Visible == true && Result_2.Visible == false)
            {
                Result_1.Visible = false;
                Result_1.Text = "";
                Result_2.Visible = true;
                Result_2.Text = ResultString;
                Result_2.ForeColor = color;
            }
            else if (Result_1.Visible == false && Result_2.Visible == true)
            {
                Result_2.Visible = false;
                Result_2.Text = "";
                Result_1.Visible = true;
                Result_1.Text = ResultString;
                Result_1.ForeColor = color;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //綁定
            string sql = "UPDATE dbo.BindingInfo SET SuctionValue = '" + label2.Text.Trim() + @"',SuctionTime=getdate() 
                       WHERE Main = N'" + Main.Text.Trim() + "' and Line='" + Util.PublicVar.Line + "'";
            if (Util.SQLHelper.ExecuteNonQuery(sql) > 0)
            {
                ResultDisplay("已上傳", Color.Black);
            }
            else
            {
                ResultDisplay("未上傳", Color.Red);
            }
            Main.Text = "";
            Main.Focus();
            Query();
        }

        private void Main_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                F();

                //檢查主機唯一性
                string sql = "select count(ID) from dbo.BindingInfo where Main=N'" + Main.Text.Trim() + "'";
                if ((int)Util.SQLHelper.ExecuteScalar(sql) == 0)
                {
                    ResultDisplay("主機未掃碼", Color.Red);
                    Main.Text = "";
                    Main.Focus();
                    return;
                }
                sql = "select count(ID) from dbo.BindingInfo where Main=N'" + Main.Text.Trim() + "' and DiPa is null";
                if ((int)Util.SQLHelper.ExecuteScalar(sql) >= 1)
                {
                    ResultDisplay("地扒未掃碼", Color.Red);
                    Main.Text = "";
                    Main.Focus();
                    return;
                }
                ////檢查吸力工序是否有做
                //sql = "select count(ID) from dbo.BindingInfo where Main=N'" + Main.Text.Trim() + "' and SuctionValue is not null";
                //if ((int)Util.SQLHelper.ExecuteScalar(sql) >= 1)
                //{
                //    ResultDisplay("吸力已測試", Color.Red);
                //    Main.Text = "";
                //    Main.Focus();
                //    return;
                //}
                //ResultDisplay("主機OK", Color.Black);
                ////Main.Focus();

                sql = "UPDATE dbo.BindingInfo SET SuctionValue = '" + label2.Text.Trim() + @"',SuctionTime=getdate() 
                       WHERE Main = N'" + Main.Text.Trim() + "' and Line='" + Util.PublicVar.Line + "'";
                if (Util.SQLHelper.ExecuteNonQuery(sql) > 0)
                {
                    ResultDisplay("已上傳", Color.Black);
                }
                else
                {
                    ResultDisplay("未上傳", Color.Red);
                }
                Main.Text = "";
                Main.Focus();
                Query();
            }
        }


        [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
        public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);
        /// <summary>      
        /// 释放内存      
        /// </summary>      
        public static void ClearMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
            }
        }
        [System.Security.SecurityCritical]
        public static void EndNoGCRegion()
        {
            if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion)
                GC.EndNoGCRegion();
        }
        private void button2_Click(object sender, EventArgs e)
        {

        }
    }
}
  • 写回答

2条回答 默认 最新

  • threenewbee 2020-04-21 09:47
    关注

    用CLR Profiler检查下内存泄漏
    用system.windows.forms.timer不要用system.timer看看
    调用的类有没有dispose的

    评论

报告相同问题?

悬赏问题

  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样