多线程访问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