多线程访问COM口 500ms 轮询一次 给串口发送命令并写日志,采用一问一答方式(就是给串口发送询问命令,串口连接的下位机接到信息后反馈给串口,然后接收反馈的信息并写日志),为什么我的程序  会有时候出现两个连续的询问,代码粘贴如下,有做多线程的高手帮帮忙。 namespace WindowsFormsApplication1 

    public partial class Form3 : Form 
    { 
        public Form3() 
        { 
            InitializeComponent(); 
        } 
        static int i = 8; 
        Thread[] thread = new Thread[i]; 
        public void BeginThread() 
        { 
            for (int m = 0; m < i; m ++) 
            { 
                ComName = m + 1; 
                thread[m] = new Thread(new ThreadStart(Run)); 
                thread[m].Priority = ThreadPriority.Normal; 
                thread[m].Start(); 
                Thread.Sleep(50); 
            } 
        } 
        private void button1_Click(object sender, EventArgs e) 
        { 
            timer1.Start(); 
            this.button1.Enabled = false; 
            this.button2.Enabled = true; 
            this.button3.Enabled = false; 
        }         private void Run() 
        { 
            try 
            { 
                ComWrite com = new ComWrite(); 
                Byte[] _OutputData = { 0xFA, 0xE1, 0x01, 0x50, 0x00, 0x17, 0x30, 0x20, 0x09, 0x12, 0x10, 0x15, 0x54, 0x46, 0x00, 0x01, 0x00, 0x00, 0x03, 0x02, 0x02, 0x00, 0x00, 0xBA, 0x18 }; 
                com.OutputBuffer = _OutputData; 
                com.PortNumber = (byte)ComName; 
                com.SendData(); 
            } 
            catch (Exception ex) 
            { 
                ComClass.WriteLog(ex.Message, i.ToString()); 
                MessageBox.Show(ex.Message); 
            } 
        } 
        private void timer1_Tick(object sender, EventArgs e) 
        { 
            BeginThread(); 
        } 
        private void button2_Click(object sender, EventArgs e) 
        { 
            timer1.Stop(); 
            this.button1.Enabled = true; 
            this.button2.Enabled = false; 
            this.button3.Enabled = true; 
        }         private void button3_Click(object sender, EventArgs e) 
        { 
            Application.Exit(); 
            CloseProcess(); 
        }         private void Form3_FormClosed(object sender, FormClosedEventArgs e) 
        { 
            Application.Exit(); 
        }         private int _comName = 0; 
        public int ComName 
        { 
            get { return _comName; } 
            set { _comName = value; } 
        } 
    } 

namespace WindowsFormsApplication1 

    public class ComWrite 
    { 
        public ComWrite() 
        { 
        } 
        private Byte[] _InputBuffer; 
        public Byte[] InputBuffer { get { return _InputBuffer; } }         private Byte[] _OutputBuffer; 
        public Byte[] OutputBuffer { set { _OutputBuffer = value; } } 
        private byte _PortNumber; 
        public byte PortNumber { get { return _PortNumber; } set { _PortNumber = value; } } 
        public void SendData() 
        { 
            try 
            { 
                _InputBuffer = SendDataToSerialPort(_PortNumber, 9600, 500, _OutputBuffer); 
            } 
            catch 
            { 
            } 
        } 
        public byte[] SendDataToSerialPort(Byte APortNo, int ABautrate, Int16 ATimeout, Byte[] AOutputData) 
        { 
            CommonAdapter ca = new CommonAdapter(APortNo, ABautrate, ATimeout); 
            ca.OutputData = AOutputData; 
            ca.SendCMD(); 
            return ca.InputData; 
        } 
    } 

解决方案 »

  1.   

    接上 namespace WindowsFormsApplication1 

        public class CommonAdapter 
        { 
            DataBase db = new DataBase(); 
            static StreamWriter strmWrt; 
            private SerialPort FComm; 
            private Byte _PortNo; 
            private int _TimeOut; 
            private Semaphore smpMain, smpLog;         private Byte[] _OutputData;//发送缓冲区 
            public Byte[] OutputData 
            { 
                set 
                { 
                    _OutputData = value; 
                } 
            } 
            private Byte[] _InputData;//接收的有效数据 
            public Byte[] InputData 
            { 
                get 
                { return _InputData; } 
            }         public CommonAdapter(Byte APortNo, int ABaudrate, int ATimeout) 
            { 
                using (FComm = new SerialPort()) 
                { 
                    FComm.DataBits = 8;//8位数据位 
                    FComm.StopBits = StopBits.One;//1位停止位 
                    FComm.Parity = Parity.None;//无校验位 
                    FComm.ReadBufferSize = 20480; 
                    FComm.WriteBufferSize = 20480;//设置读写缓冲区长度各为20K字节                 _PortNo = APortNo; 
                    string smpComName = string.Format("COM{0}", _PortNo); 
                    FComm.PortName = smpComName; 
                    FComm.BaudRate = ABaudrate;//波特率为自定义 
                    _TimeOut = ATimeout; 
                    FComm.ReadTimeout = _TimeOut;                 _InputData = new Byte[1]; 
                    FComm.Dispose(); 
                } 
            } 
            private String ConvertTo(Byte[] Buf) 
            { 
                StringBuilder sb = new StringBuilder(Buf.Length * 3); 
                foreach (Byte b in Buf) 
                { 
                    sb.Append(" "); 
                    sb.Append(b.ToString("X2")); 
                } 
                return sb.ToString(); 
            } 
            private void WriteLog(Byte[] Buf, Byte OpType, string ComName) 
            { 
                String LogFormat = ""; 
                switch (OpType) 
                { 
                    case 0: 
                        LogFormat = "{0:HH:mm:ss.fff} COM{1} Send({2:D2}B): {3}"; 
                        break; 
                    case 1: 
                        LogFormat = "{0:HH:mm:ss.fff} COM{1} Recv({2:D2}B): {3}"; 
                        break; 
                    default: 
                        break; 
                } 
                string smpLogName = "SerialPortIOLog"; 
                Boolean b; 
                try 
                { 
                    Random ro = new Random(); 
                    Thread.Sleep(ro.Next(30)); 
                    smpLog = Semaphore.OpenExisting(smpLogName); 
                } 
                catch (WaitHandleCannotBeOpenedException) 
                { 
                    string user = Environment.UserDomainName + "\\" + Environment.UserName; 
                    SemaphoreSecurity sSec = new SemaphoreSecurity();                 SemaphoreAccessRule rule = new SemaphoreAccessRule(user, SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow); 
                    sSec.AddAccessRule(rule);                 rule = new SemaphoreAccessRule(user, SemaphoreRights.ReadPermissions | SemaphoreRights.ChangePermissions, AccessControlType.Allow); 
                    sSec.AddAccessRule(rule); 
                    while (true) 
                    { 
                        try 
                        { 
                            smpLog = new Semaphore(1, 1, smpLogName, out b, sSec); 
                            break; 
                        } 
                        catch (Exception) 
                        {                         Thread.Sleep(10); 
                        }                 } 
                } 
                catch (UnauthorizedAccessException) 
                { 
                    SemaphoreSecurity mSec = smpLog.GetAccessControl();                 string user = Environment.UserDomainName + "\\" + Environment.UserName; 
                    SemaphoreAccessRule rule = new SemaphoreAccessRule(user, SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow); 
                    mSec.RemoveAccessRule(rule); 
                    rule = new SemaphoreAccessRule(user, SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow); 
                    mSec.AddAccessRule(rule); 
                    smpLog.SetAccessControl(mSec); 
                    smpLog = Semaphore.OpenExisting(smpLogName); 
                } 
                catch (Exception) 
                { 
                    throw; 
                }; 
                string LogRoot = ConfigurationManager.AppSettings["LogPath"]; 
                string _LogFilePath = LogRoot + string.Format(@"\\" + ComName + "{0:yyyyMMdd}.log", DateTime.Today); 
                smpLog.WaitOne();//等待信号量释放,然后获取信号量控制权 
                try 
                { 
                    DataBase db = new DataBase(); 
                    try 
                    { 
                        strmWrt = new StreamWriter(_LogFilePath, true, System.Text.Encoding.ASCII); 
                        strmWrt.WriteLine(LogFormat, DateTime.Now, _PortNo, Buf.Length, ConvertTo(Buf)); 
                        strmWrt.Flush();  
                    } 
                    catch (IOException) 
                    { 
                        strmWrt.WriteLine(LogFormat, DateTime.Now, _PortNo, Buf.Length, ConvertTo(Buf)); 
                        strmWrt.Flush(); 
                    } 
                    finally 
                    { 
                        strmWrt.Dispose(); 
                    } 
                    Thread.Sleep(30);//等待数据写盘  
                } 
                finally 
                { 
                    smpLog.Release();//释放信号量控制权 
                } 
            }  
      

  2.   

    public void SendCMD() 
            { 
                //db.InserDebugLog("Start:SendCMD",(int)_PortNo-1); 
                WriteLog(this._OutputData, 0, string.Format("COM{0:D2}", _PortNo)); 
                string smpComName = string.Format("COM{0:D2}", _PortNo); 
                bool b; 
                try 
                { 
                    smpMain = Semaphore.OpenExisting(smpComName); 
                } 
                catch (WaitHandleCannotBeOpenedException) 
                { 
                    string user = Environment.UserDomainName + "\\" + Environment.UserName; 
                    SemaphoreSecurity sSec = new SemaphoreSecurity(); 
                    SemaphoreAccessRule rule = new SemaphoreAccessRule(user, SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow); 
                    sSec.AddAccessRule(rule);                 rule = new SemaphoreAccessRule(user, SemaphoreRights.ReadPermissions | SemaphoreRights.ChangePermissions, AccessControlType.Allow); 
                    sSec.AddAccessRule(rule); 
                    while (true) 
                    { 
                        try 
                        { 
                            smpMain = new Semaphore(1, 1, smpComName, out b, sSec); 
                            break; 
                        } 
                        catch (Exception) 
                        { 
                            Thread.Sleep(10); 
                        }                 } 
                } 
                catch (UnauthorizedAccessException) 
                { 
                    SemaphoreSecurity mSec = smpMain.GetAccessControl(); 
                    string user = Environment.UserDomainName + "\\" + Environment.UserName; 
                    SemaphoreAccessRule rule = new SemaphoreAccessRule(user, SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow); 
                    mSec.RemoveAccessRule(rule); 
                    rule = new SemaphoreAccessRule(user, SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow); 
                    mSec.AddAccessRule(rule); 
                    smpMain.SetAccessControl(mSec); 
                    smpMain = Semaphore.OpenExisting(smpComName); 
                } 
                catch (Exception) 
                { 
                    throw; 
                } 
                smpMain.WaitOne();//等待信号量释放,然后获取 
                try 
                { 
                    if (FComm.IsOpen) 
                    { 
                        FComm.DiscardInBuffer(); 
                        FComm.DiscardOutBuffer();//清除缓冲区 
                        FComm.Close();//关闭串口 
                    } 
                    try 
                    { 
                        FComm.Open();//打开串口 
                    } 
                    catch (Exception) 
                    { 
                        return; 
                    } 
                    try 
                    { 
                        FComm.Write(_OutputData, 0, _OutputData.Length); 
                        Array.Clear(_InputData, 0, _InputData.Length); 
                        Array.Resize(ref _InputData, 0); 
                        Byte FirstByte; 
                        try 
                        { 
                            FirstByte = (Byte)FComm.ReadByte(); 
                        } 
                        catch (TimeoutException) 
                        { 
                            WriteLog(new Byte[] { }, 1, string.Format("COM{0:D2}", _PortNo)); 
                            return; 
                        } 
                        catch (Exception) 
                        { 
                            throw; 
                        } 
                        Array.Resize(ref _InputData, 1); 
                        _InputData[0] = FirstByte; 
                        while (true) 
                        { 
                            Thread.Sleep(20);//字节间超时20毫秒 
                            int BufferLength = 0; 
                            int InputLength = _InputData.Length; 
                            BufferLength = FComm.BytesToRead;//检测接收缓冲区有效字节长度 
                            if (BufferLength == 0) 
                            { 
                                break; 
                            } 
                            Array.Resize(ref _InputData, InputLength + BufferLength); 
                            FComm.Read(_InputData, InputLength, BufferLength);//读取有效字节 
                        } 
                        WriteLog(this._InputData, 1, string.Format("COM{0:D2}", _PortNo)); 
                    } 
                    finally 
                    { 
                        if (FComm.IsOpen) 
                        { 
                            FComm.DiscardInBuffer(); 
                            FComm.DiscardOutBuffer();//清除缓冲区 
                            FComm.Close(); 
                        } 
                        FComm.Dispose(); 
                    } 
                } 
                finally 
                { 
                    //db.InserDebugLog("End:SendCMD",(int)_PortNo-1); 
                    smpMain.Release();//释放信号量 
                } 
            } 
        } 
    } 想要的是这种情况 
    10:38:29.319 COM1 Send(25B):  FA E1 01 01 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18 
    10:38:29.866 COM1 Recv(00B): 
    10:38:29.898 COM1 Send(25B):  FA E1 01 02 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18 
    10:38:30.446 COM1 Recv(00B): 
    10:38:30.533 COM1 Send(25B):  FA E1 01 03 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18 
    10:38:31.082 COM1 Recv(00B): 
    现在的情况是这样的 
    10:38:30.852 COM7 Send(25B):  FA E1 01 03 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18 
    10:38:31.456 COM7 Send(25B):  FA E1 01 04 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18 
    10:38:31.487 COM7 Recv(00B): 
    10:38:32.044 COM7 Send(25B):  FA E1 01 05 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18 
    10:38:32.606 COM7 Recv(00B): 
    10:38:32.699 COM7 Send(25B):  FA E1 01 06 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18 
    10:38:33.317 COM7 Send(25B):  FA E1 01 07 00 17 30 20 09 12 10 15 54 46 00 01 00 00 03 02 02 00 00 BA 18