当前位置: 首页 > article >正文

C#编写上位机通过OPC DA读取西门子PLC数据

Sync_RW

引用:Quick.OpcComRcw

文档中原程序会报错:

原因:需要在安装有Simatic NET V14的电脑上运行这个程序。

需要注释掉下面程序,否则读取时会无故障提示退出。

 //finally里的程序要注释掉,否则一点击read按钮,程序会直接无故障提示退出
            //finally
            //{
            //    // Free the unmanaged memory
            //    if (pItemValues != IntPtr.Zero)
            //    {
            //        Marshal.FreeCoTaskMem(pItemValues);
            //        pItemValues = IntPtr.Zero;
            //    }
            //    if (pErrors != IntPtr.Zero)
            //    {
            //        Marshal.FreeCoTaskMem(pErrors);
            //        pErrors = IntPtr.Zero;
            //    }
            //}

可能的原因:

  1. 访问违规(Access Violation):如果Marshal.PtrToStructure在尝试转换指针时指向了无效的内存地址,可能会导致访问违规。
  2. 内存泄漏/损坏:在调用Marshal.PtrToStructure之前,如果指针已经被释放或者被错误地使用,可能会引发问题。
  3. 线程问题:如果UI操作在非UI线程上执行,可能会导致未预期的行为。
  4. 资源释放问题:在finally块中,如果Marshal.FreeCoTaskMem被调用两次,可能会引发问题。

其他解决方案:(未测试)

1.增强异常处理:您可以在按钮点击事件处理程序的外围添加额外的异常处理,以确保任何未捕获的异常都能被捕获并记录下来。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    // 在窗体关闭之前检查是否有未处理的异常
    if (Environment.HasShutdownStarted == false)
    {
        e.Cancel = true;
        MessageBox.Show("An unexpected error has occurred. The application will now close.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

// 在Main方法中注册全局异常处理
[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
    
    try
    {
        Application.Run(new Form1());
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
    MessageBox.Show(e.Exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    MessageBox.Show((e.ExceptionObject as Exception).Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
  1. 检查内存操作:确保在调用Marshal.PtrToStructure之前,指针是有效的,并且不要在释放内存之后再次使用指针。
  2. 线程同步:确保UI更新在UI线程上执行。
  3. 调试:使用调试器运行程序,并设置断点以检查Marshal.PtrToStructure调用之前和之后的指针状态。检查是否有任何访问违规或其他异常。
  4. 日志记录:在代码的关键部分添加日志记录,以便在程序崩溃时能够更好地理解发生了什么。

请注意,由于Marshal.PtrToStructure和内存管理涉及非托管代码,错误可能很难追踪。如果您不确定如何处理,请确保遵循正确的内存管理实践,并考虑使用更高级别的库来处理OPC通信,这样可以减少直接与内存和指针打交道的风险。


http://www.kler.cn/a/293157.html

相关文章:

  • 使用 unicorn 和 capstone 库来模拟 ARM Thumb 指令的执行(一)
  • C++ 并发专题 - 自旋锁的实现(Spinlock)
  • 【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)
  • 陪诊问诊APP开发实战:基于互联网医院系统源码的搭建详解
  • MQTT协议解析 : 物联网领域的最佳选择
  • HBase理论_背景特点及数据单元及与Hive对比
  • 大数据开发:可视化组件Redash安装部署
  • springboot整合logback进行日志管理(上篇)
  • etc bashrc和 etc profile傻傻分不清楚?_
  • 怎么在mathtype中打空格 MathType空格键不能用
  • WHAT - React 函数与 useMemo vs useCallback
  • Redis安装步骤——离线安装与在线安装详解
  • 基于uniapp的登录状态保持(APP免登录)
  • 基于yolov8的西红柿检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
  • 【QT】十分钟全面理解 信号与槽的机制
  • Java并发编程实战 04 | 使用WaitNotify时要注意什么?
  • 黑马点评6——优惠券秒杀—Redis消息队列实现异步秒杀
  • 智联云采 SRM2.0 autologin 身份认证绕过漏洞复现
  • Spring、SpringMVC、SpringBoot都是什么,有什么区别
  • 如何使用事件流相关操作
  • Maven聚合与继承
  • 11、Django Admin启用对计算字段的过滤
  • 大数据-111 Flink 安装部署 YARN部署模式 FlinkYARN模式申请资源、提交任务
  • Java反射机制讲解
  • C++set与map容器
  • 10Python的Pandas:样式Style