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

相关推荐
__water24 分钟前
『功能项目』QFrameWork框架重构OnGUI【63】
c#·unity引擎·重构背包框架
Crazy Struggle43 分钟前
C# + WPF 音频播放器 界面优雅,体验良好
c#·wpf·音频播放器·本地播放器
晨曦_子画1 小时前
C#实现指南:将文件夹与exe合并为一个exe
c#
花开莫与流年错_2 小时前
C# 继承父类,base指定构造函数
开发语言·c#·继承·base·构造函数
hillstream32 小时前
oracle中NUMBER(1,0)的字段如何映射到c#中
数据库·oracle·c#
那个那个鱼2 小时前
.NET 框架版本年表
开发语言·c#·.net
莱茶荼菜3 小时前
使用c#制作一个小型桌面程序
开发语言·opencv·c#
Red Red4 小时前
GEO数据库提取疾病样本和正常样本|GEO数据库区分疾病和正常样本|直接用|生物信息|生信
开发语言·数据库·笔记·学习·r语言·c#·生物信息
Zhen (Evan) Wang6 小时前
What is the new in C#11?
开发语言·c#
IT规划师10 小时前
C#|.net core 基础 - 值传递 vs 引用传递
c#·.netcore·值传递·引用传递