我有以下代码来处理来自服务器的更改通知:
//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窗体会抛出有关跨线程操作无效的异常。
记录器函数只是将时间-值对添加到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函数结束?任何帮助都将不胜感激。作为一种快速解决方法,如何从与窗体更新相同的事件处理程序中同步调用记录器?
发布于 2020-07-24 14:52:13
我认为monitoredItem
可能在下一次活动中发生了变化。
首先尝试DequeueValues
,然后传递到BeginInvoke
部件中。
只需使用BeginInvoke
更新UI即可。
如果您的日志方法不更新UI。同步调用它。
https://stackoverflow.com/questions/63066586
复制相似问题