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

相关推荐
钢铁男儿1 小时前
C# 类和继承(扩展方法)
java·servlet·c#
爱炸薯条的小朋友2 小时前
C#由于获取WPF窗口名称造成的异常报错问题
windows·c#·wpf
Rose 使者4 小时前
全球IP归属地查询接口如何用C#进行调用?
c#·api·ip地址
~plus~5 小时前
Harmony核心:动态方法修补与.NET游戏Mod开发
开发语言·jvm·经验分享·后端·程序人生·c#
htj106 小时前
C# 使用正则表达式
正则表达式·c#
~plus~6 小时前
WPF八大法则:告别模态窗口卡顿
开发语言·经验分享·后端·程序人生·c#
就是有点傻6 小时前
使用WPF的Microsoft.Xaml.Behaviors.Wpf中通用 UI 元素事件
c#
qq_297908016 小时前
C#报价系统陈列展示成本核算系统项目管理系统纸品非纸品报价软件
sqlserver·c#·.net·开源软件
CoderIsArt15 小时前
C#中的CLR属性、依赖属性与附加属性
c#
IGP920 小时前
20250606-C#知识:委托和事件
开发语言·c#