这是一篇关于软件性能方面的文章,源于我在项目中遇到的问题引发的一些思考。
问题背景:
在项目中设计到这样一个界面,当点击刷新按钮时候,上位机软件遍历下图中的所配置的节点,遍历的过程中根据每个节点的信息生成指令与嵌入式设备进行通信,嵌入式设备响应后,上位机软件在该图中的节点中显示检测结果。
解决方案一:
点击刷新后,界面线程创建一个新的线程,这个线程负责与下位机通信,在一个事件上等待,直到下位机返回检测结果,并将通信的结果显示在界面上,这是使事件授信,该线程发送下一组指令,直到所有节点检测完毕。这里非界面线程不能直接操作界面线程创建的控件,在.net平台上是通过委托方式实现的,代码如下:
private bool SetEcuBacColor(string strElement, string strStyle)
{
bool bstatus = false;
if (this.Browser.InvokeRequired)
{
SetDlg HideOrDisplayFunc = new SetDlg(SetEcuBacColor);
this.Browser.Invoke(HideOrDisplayFunc, strElement, strStyle);
}
else
{
HtmlElement Element = Browser.Document.All[strElement];
if (null != Element)
{
Element.Style = strStyle;
bstatus = true;
}
}
return bstatus;
}
上面的函数是修改上图中矩形的背景色的实现。
在这个方案中,界面线程等待用户触发事件。
执行线程负责与下位机通信,然后通过委托的方式来把来更新界面,这里负责检测与更新检测结果都是在执行线程完成的,这样完成整个检测过程,发费很长时间。
怎么让检测速度更快呢?也就是说怎么让界面线程分担一些执行线程的任务??
方案二:
执行线程执行节点的检测,然后通过事件的方式,把检测结果发送给界面线程,让界面线程执行节点的更新操作,这样让界面线程分摊了执行线程的部分CPU时间。
//发送事件
public event EventHandler<DiagnoseEventArgs> DignoseResult;
if (null != DignoseResult)
{
DignoseResult(this, new DiagnoseEventArgs(iDtcs, DiagnoseStatus));
}
return true;
}
private bool IsDisconnect(string strHexPdu)
{
bool status = false;
try
{
string strFlag = strHexPdu.Substring(2, 2);
if (strFlag == "40")
{
status = true;
}
}
catch (System.Exception ex)
{
LogRecord.GetInstance().WriteLog(TypeDefine.LOG_LEVEL.ERROR, ex.Message);
}
return status;
}
}
public class DiagnoseEventArgs : EventArgs
{
public DiagnoseEventArgs(int DtcNumber, Status ConnectStatus,string CurElement, string DtcElement, string GElement)
{
this.ConnectStatus = ConnectStatus;
this.GElement = GElement;
}
public string CurElement { get; private set; }
public Status ConnectStatus { get; private set; }
}
方案二通过任务分摊的方式,用户友好程度明显好于方案一.