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通信,这样可以减少直接与内存和指针打交道的风险。

相关推荐
CodeCraft Studio4 小时前
PPT处理控件Aspose.Slides教程:使用 C# 将 PPTX 转换为 EMF
c#·powerpoint·ppt·aspose·ppt格式转换
future14125 小时前
游戏开发日记7.12
数据结构·学习·c#·游戏开发
洁辉6 小时前
C# & .NET 面试深度复习指南
面试·c#·.net
_oP_i8 小时前
无法找到来自源 EdgeWebView,实际安装了,偶尔出现
c#
阿蒙Amon9 小时前
C#类型转换:从基础到进阶的全景解析
开发语言·c#
时光追逐者15 小时前
一款开源免费、通用的 WPF 主题控件包
开源·c#·.net·wpf
张人玉18 小时前
c#中Random类、DateTime类、String类
开发语言·c#
future141219 小时前
游戏开发日记
数据结构·学习·c#
军训猫猫头21 小时前
3.检查函数 if (!CheckStart()) return 的妙用 C#例子
开发语言·c#
yngsqq1 天前
netdxf—— CAD c#二次开发之(netDxf 处理 DXF 文件)
java·前端·c#