【问题标题】:Notification handling with Windows Forms使用 Windows 窗体处理通知
【发布时间】: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


    【解决方案1】:

    我想monitoredItem 可能会在下一次活动中更改。

    先尝试DequeueValues,然后传入BeginInvoke部分。

    只需使用 BeginInvoke 更新 UI。

    如果您的日志方法不更新 UI。同步调用。

    【讨论】:

    • 是的,谢谢,我试过这样做,但如果我在 beginInvoke 部分之前做任何事情,它会引发跨线程异常。我所做的是我将两个事件处理程序都订阅了同一个事件,并且它现在可以正常工作。丑陋的解决方案,行为仍未完全理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 2019-10-27
    • 2011-09-26
    • 2018-12-22
    • 2010-12-02
    • 2011-09-23
    • 1970-01-01
    相关资源
    最近更新 更多