多线程访问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;
}
}
}
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;
}
}
}
{
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();//释放信号量控制权
}
}
急!急!急!急!急!急!急!
只有这么多分了 全给了
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