关于异步等待的问题,求求大家指点下

caomolai78695476 2010-09-08 09:19:09
我的问题是要把多块表的抄表时间发到单片机上去,现在功能实现,比如我写入一个表具的抄表时间,成功后里面会反馈消息,我根据消息好做下一步处理,现在问题出在这块

if (pCI != null&&model.Comm.ToString().Equals(pCI.PortNum.ToString()))
{
Tools.ShowContentHint(string.Format("采集串口 " + pCI.PortNum.ToString() + " 开始初始化抄表 CDT编号:{0} 安装序号{1}",model.CdtNum,model.SerialNo));
// 等待通道可利用
while (!pCI.IsAvailable)
{
Thread.Sleep(1000 * Config.SendInterval);
}
pCI.IsAvailable = false;
pCI.SPUnit.WaitEvent.Reset();
pCI.SPUnit.SendData(InstructionSet.GetInitReadTimeCommandCmd(cdt, meter, model));
if (!pCI.SPUnit.WaitEvent.WaitOne(6000, false))
{
#region
// 我的想法是发送后让线程等待6S,如果6S后还没接收完或没反馈就当超时处理,跟踪是有反馈的,就是进不来。
// 我修改为WaitOne(-1, false)为无限等待也不行,主要对这WaitOne不理解,查了资料还不明白,所以请教大侠

string pReturnStr = InstructionSet.ByteToHexString(pCI.SPUnit.pbReceiveArr, true);

#endregion
}
else
{
Tools.ShowContentHint(string.Format("采集串口 " + pCI.PortNum.ToString() + " CDT编号:{0} 安装序号{1} 无应答反馈", model.CdtNum, model.SerialNo));
}
pCI.IsAvailable = true;
}

#endregion
}
pCI.SPUnit.CloseComm();
}



============================================================= 调用部分=================================================================
/// <summary>
/// 发送抄表配置信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendPlan_Click(object sender, EventArgs e)
{
#region

if (this.dgvPlan.CurrentRow != null)
{
int planId = PublicBasis.DataTypeHelper.GetInt(this.dgvPlan.CurrentRow.Cells["CPlanID"].Value);
List<M_PlanDetail> details = new SC.SSH.BLL.BLLM_PlanDetail().GetModelList(string.Format("PlanId={0} and IsSend=0", planId));

IList<string> comms = new List<string>();
foreach (SC.SSH.Model.M_PlanDetail model in details)
{
if (!comms.Contains(model.Comm.ToString()))
{
comms.Add(model.Comm.ToString());
}
}

// 初始化串口实例
foreach (string comm in comms)
{
SerialPortUnit serialPort = new SerialPortUnit("COM" + comm);
Task pCI = new Task();
pCI.PortNum = DataTypeHelper.GetInt(comm);
pCI.SPUnit = serialPort;
pCI.details = details;

// 异步初始化抄表时间
NewTaskDelegate pInitTime = new NewTaskDelegate(InitTime);
IAsyncResult pInitTimeResult = pInitTime.BeginInvoke(pCI, null, null);
}
}
else
{
MessageBox.Show("请选择需要发送的计划");
}

#endregion
}

====================================================================这是我封装的一个任务类===================================================
/// <summary>
/// 抄表任务
/// </summary>
public class Task
{
/// <summary>
/// 串口号
/// </summary>
public int? PortNum=null;

/// <summary>
/// 串口对象类
/// </summary>
public SerialPortUnit SPUnit;

/// <summary>
/// 计划从表
/// </summary>
public IList<M_PlanDetail> PlanDetails;

/// <summary>
/// 广播校时时间:00:10:00
/// 当校时完毕后修改广播校时时间为下一天的00:10:00
/// </summary>
public DateTime BroadCastTime = PublicBasis.DataTypeHelper.GetDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:10:00")).AddDays(1);

/// <summary>
/// 下次读表时间,此时间是后台定时轮训时间
/// 和抄表计划中的时间不同
/// </summary>
public DateTime NextTime = DateTime.Now;

/// <summary>
/// 下次轮训报警时间
/// </summary>
public DateTime NextCheckWaringTime = DateTime.Now;

/// <summary>
/// 串口是否可用
/// </summary>
public bool IsAvailable = true;

/// <summary>
/// 当前抄码对象
/// </summary>
public CurrPlanDetail CurrPlanDetail;

/// <summary>
/// 初始化CurrPlanDetail
/// </summary>
/// <returns></returns>
public CurrPlanDetail InitCurrPlanDetail(M_PlanDetail model)
{
CurrPlanDetail cpd = new CurrPlanDetail();
PublicBasis.DataTypeHelper.Clone(cpd.planDetail, model);
return cpd;
}

/// <summary>
///
/// </summary>
public List<M_PlanDetail> details;

public List<M_ControlPlanDetail> M_ControlPlanDetails;
}
}

...全文
143 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
caomolai78695476 2011-01-05
  • 打赏
  • 举报
回复
已解决。
利用异步多线程,发送-》延时-》等待
caomolai78695476 2010-09-08
  • 打赏
  • 举报
回复
希望大家耐心看哈
caomolai78695476 2010-09-08
  • 打赏
  • 举报
回复
=================================================================串口操作类=======================================================================
public class SerialPortUnit
{

#region 公共事件

public delegate void Func(params object[] values);

public delegate void DataArrivedHandler(byte[] dataReceived, int sizeReceived, string portName);

public event DataArrivedHandler DataArrived;

#endregion

#region 私有属性

private SerialPort sp = new SerialPort(); //创建一个串口类

public AutoResetEvent WaitEvent = new AutoResetEvent(false); //创建一个线程事件

private int _ReadTimeout; //读数据超时(从开始收数据到所有数据接收完用的时间)

private string _ErrMsg; //错误信息

private DateTime lastTimeing = PublicBasis.DataTypeHelper.GetDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:10:00"));

#endregion

#region 公共接口

/// <summary>
/// 错误信息
/// </summary>
public string ErrMsg
{
get
{
return _ErrMsg;
}
}

/// <summary>
/// 上次校时时间
/// </summary>
public DateTime LastTiming
{
get
{
return lastTimeing;
}
set
{
lastTimeing = value;
}
}

#endregion

#region 静态属性

/// <summary>
/// 串口号:COM1
/// </summary>
public string PortName = "COM1";

/// <summary>
/// 波特率:9600
/// </summary>
public int BaudRate = 4800;

/// <summary>
/// 停止位:1
/// </summary>
public int StopBit = 1;

/// <summary>
/// 数据位:8
/// </summary>
public int DataBit = 8;

/// <summary>
/// 校验位:0
/// </summary>
public int CheckBit = 0;

#endregion

#region 发送、接收数据属性

private byte[] pbSendArr; //待发送数据

private int pbSendArrLength; //待发送数组长度

//public string pstrSend; //转化为字符串的待发送数据

public byte[] pbReceiveArr; //接收数据数组

private int pbReceiveArrLength; //接收数据的长度

public string pStrReceive; //接收到得数据字符串,已经转换成16进制的字符串

#endregion


/// <summary>
/// 清空错误信息
/// </summary>
private void ClearError()
{
_ErrMsg = string.Empty;
}

/// <summary>
///
/// </summary>
/// <param name="value"></param>
private void SetError(string value)
{
_ErrMsg = value;
}


/// <summary>
///
/// </summary>
/// <param name="seconds"></param>
public void Sleep(float seconds)
{
Application.DoEvents();
Thread.Sleep((int)(seconds * 1000));
Application.DoEvents();
}

/// <summary>
/// 构造函数
/// </summary>
public SerialPortUnit(string portName)
{
#region

PortName = portName;
sp.PortName = PortName;
sp.BaudRate = BaudRate;
sp.Parity = (System.IO.Ports.Parity)CheckBit;
sp.DataBits = DataBit;
sp.StopBits = (System.IO.Ports.StopBits)StopBit;
sp.Handshake = System.IO.Ports.Handshake.None;
this.sp.ReadBufferSize = 4096;
this.sp.WriteBufferSize = 4096;
this.pbSendArr = new byte[this.sp.WriteBufferSize];
this.pbReceiveArr = new byte[this.sp.ReadBufferSize];
this._ReadTimeout = 3000;
this.sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

#endregion
}


/// <summary>
///
/// </summary>
public void InitCom()
{
#region

sp.PortName = PortName;
sp.BaudRate = BaudRate;
sp.Parity = (System.IO.Ports.Parity)CheckBit;
sp.DataBits = DataBit;
sp.StopBits = (System.IO.Ports.StopBits)StopBit;
sp.Handshake = System.IO.Ports.Handshake.None;

#endregion
}

bool bDataReceived = true;

/// <summary>
/// 串口接收数据事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
#region

//Sleep(2f);
bDataReceived = true;
ClearInBuffer();
bool result = ReceiveData();
WaitEvent.Set();

#endregion
}

/// <summary>
/// 自动接收数据
/// </summary>
/// <returns></returns>
private bool ReceiveData()
{
#region

int iLen = 0;
try
{

while (bDataReceived)
{
bDataReceived = false;
ClearError();

// 取发送过来的数据长度
iLen = sp.BytesToRead;
if (iLen > 0)
{
pbReceiveArr = new byte[iLen];
sp.Read(pbReceiveArr, 0, iLen);
bDataReceived = true;
}

Sleep(0f);
if (bDataReceived && DataArrived != null)
{
DataArrived(pbReceiveArr, iLen, PortName);
bDataReceived = false;
}
}
}
catch (Exception e)
{
SetError(e.Message);
return false;
}
return true;

#endregion
}

#region 打开、关闭串口

/// <summary>
/// 打开串口
/// </summary>
/// <returns></returns>
public bool OpenComm()
{
#region

ClearError();

try
{

if (!sp.IsOpen)
{

InitCom();

sp.Open();

}

}

catch (Exception e)
{

SetError(e.Message);

return false;

}

return true;

#endregion
}

/// <summary>
/// 关闭串口
/// </summary>
public void CloseComm()
{
#region

try
{

if (sp.IsOpen)
{
sp.DataReceived -= new SerialDataReceivedEventHandler(sp_DataReceived);
sp.Close();

}

}

catch
{

return;

}

#endregion
}

#endregion

/// <summary>
///发送数据
///在发送前先清空发送和接收缓冲区
/// </summary>
public bool SendData()
{
#region

OpenComm();

ClearError();

bool b = true;

try
{

this.sp.DiscardInBuffer();

this.sp.DiscardOutBuffer();

// 2010-04-28
//Sleep(0.02f);

//this.sp.Write(pbSendArr, 0, pbSendArrLength);

for (int i = 0; i < pbSendArr.Length; i++)
{
this.sp.Write(pbSendArr, i, 1);
Sleep(0.01f);
}
b = true;

}

catch (Exception e)
{

SetError(e.Message);

b = false;

}

return b;
#endregion
}

/// <summary>
///
/// </summary>
/// <param name="datas"></param>
/// <returns></returns>
public bool SendData(byte[] datas)
{
#region

pbSendArr = datas;
pbSendArrLength = datas.Length;
return SendData();

#endregion
}

/// <summary>
///
/// </summary>
/// <param name="strSend"></param>
/// <returns></returns>
public bool SendData(string strSend)
{
#region

string s = " ";
char[] sc = s.ToCharArray();
string Endstr = strSend.Trim();

string[] str = Endstr.Split(sc);
Byte[] send = new Byte[str.Length];
for (int n = 0; n < str.Length; n++)
{
send[n] = byte.Parse(str[n], System.Globalization.NumberStyles.HexNumber);
}
bool result = SendData(send);
return result;

#endregion
}

/// <summary>
/// 清除接收数组内的内容
/// </summary>
private void ClearInBuffer()
{
#region

this.pbReceiveArrLength = 0;
this.pStrReceive = string.Empty;

#endregion
}
}
}
尐孑 2010-09-08
  • 打赏
  • 举报
回复
期待高手

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧