【发布时间】:2020-07-24 03:58:12
【问题描述】:
我有以下代码处理来自服务器的更改通知:
//this is the notification control to process the change value event.
public void OnNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e,
MonitorHandler mh)
{
//check which thread called OnNotification
if (this.InvokeRequired)
{
this.BeginInvoke((Action)delegate () { OnNotification(monitoredItem, e, mh); });
}
else
{
mh.monitoredItem = monitoredItem;
foreach (var value in monitoredItem.DequeueValues())
{
mh.SetValue(value);
mh.SetQuality(value);
mh.SetTimeStamp(value);
if (loggingOn)
{
//add to log
log.AddRecord(monitoredItem, value);
}
}
}
}
Windows 表单确实会更新,但程序不知何故错过了大约一半的通知。对 GUI 无关紧要,但对日志很重要。
如果我同步调用日志功能:
public void OnNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
foreach (var value in monitoredItem.DequeueValues())
{
if (loggingOn)
{
//add to log
log.AddRecord(monitoredItem, value);
}
}
}
日志可以完美运行,但是windows窗体当然会抛出关于跨线程操作无效的异常。
Logger 函数只是将时间-值对添加到 xml 文档中:
public void AddRecord(MonitoredItem item, DataValue value)
{
var str = item.DisplayName.Replace("\"", "");
//find the right element
var searchStr = "log/Tag[@Name='" + str + "']";
var tagNode = xmlDoc.SelectSingleNode(searchStr);
if (tagNode !=null)
{
var dpAdd = dpNode.CloneNode(true);
//time node
dpAdd.FirstChild.InnerText = value.ServerTimestamp.ToString("hh:mm:ss.fff");
//value node
dpAdd.LastChild.InnerText = value.WrappedValue.ToString();
tagNode.AppendChild(dpAdd);
}
}
我对这种行为感到困惑,因为即使通知来自不同的线程,它们最终都应该调用 AddRecord 函数?任何帮助,将不胜感激。作为一种快速修复,如何在表单更新时从同一个事件处理程序同步调用记录器?
【问题讨论】:
标签: c# event-handling opc