【问题标题】:Stopping Garbage Collection for an unmanaged Delegate停止非托管委托的垃圾收集
【发布时间】:2011-06-28 06:57:07
【问题描述】:

我最近一直在尝试使用R.NET 让 R 与 .NET 和 C# 对话。到目前为止一切都很顺利,但我遇到了一个我似乎无法解决的问题。

我对简单的基本命令没有任何问题。我做了一个简单的计算器,以及将数据导入数据网格的东西。但现在我不断收到以下错误:

对“R.NET!RDotNet.Internals.blah3::Invoke”类型的垃圾收集委托进行了回调。这可能会导致应用程序崩溃, 损坏和数据丢失。将委托传递给非托管代码时,它们必须 由托管应用程序保持活动状态,直到确保它们永远不会被调用。

当我尝试重复导入一个文本文件时,它开始了,只是为了测试一些东西。我以各种方式查找了此错误 - 经过数小时的网页搜索,似乎有多种原因导致此类错误。随着时间的推移,我一直在将我的代码剥离到越来越简单的任务中,以试图消除可能性。我现在有了这个:

 public Form1()
        {
            InitializeComponent();

            REngine.SetDllDirectory(@"C:\Program Files\R\R-2.13.0\bin\i386");
            REngine.CreateInstance("RDotNet");

            using (REngine currentEngine = REngine.GetInstanceFromID("RDotNet"))
            {
                for (int i = 0; i < 1000; ++i)
                {
                    currentEngine.EagerEvaluate("test <- " + i.ToString());

                    NumericVector returned = currentEngine.GetSymbol("test").AsNumeric();

                    textBox1.Text += returned[0];

                }

            }

        }

它所做的只是增加 textBox1.Text 中的计数。我一直在做一个测试,按下按钮来增加值,但这让我的手指在一段时间后感到疼痛!它通常可以在抛出上述错误之前管理大量印刷机。

起初这段代码似乎没问题 - 所以我认为我一直在做的其他事情是问题的原因,以及上面引用的错误的原因。所以这就是我放入 for 循环的原因。循环可以运行数百次而没有问题,但随后就会出现错误。

现在,我确实读到这种错误可以由垃圾收集器调用,以摆脱我一直在使用的实例。我已经尝试了我阅读的各种建议,因为我最好理解它们。这些包括使用 GC.KeepAlive() (不走运),以及在一个单独的类中创建一个无法摆脱的私有字段。遗憾的是,这也不起作用。

还有什么我可以尝试的吗?我对 C# 非常非常陌生,因此我将不胜感激有关如何使其正常工作的任何指示。我非常认为,我在建议的方法上缺乏成功要么与(1)我自己在实施标准修复时的错误(这似乎很可能)有关,要么与(2)我没有的与 R.NET 相关的怪癖有关不明白。

任何帮助将不胜感激!

【问题讨论】:

  • 您将 GC.KeepAlive 调用究竟放在哪里?这是正确的解决方法,但必须在最后一次需要之后 - 方法结束是最简单的。
  • 我不知道你的具体问题,但它让我想起了我最近反复尝试写入文本文件的类似情况。它大部分时间都有效,除了在我的下一次写入操作发生之前操作系统尚未完成关闭文件连接的那些零星情况。我知道你只是从你的文件中读取,但教训可能仍然存在:尝试以最小化文件操作次数的方式编写代码。换句话说,读取文件并将其存储在内存中,直到完成循环。
  • 我没有看到您将委托传递给非托管代码。你能添加你的那部分代码吗?
  • @Marc Gravell - 我在各种奇怪而美妙的地方调用了 KeepAlive,但它们似乎都不起作用。例如,我在上面 using 块的末尾尝试了它,但没有运气。我再次尝试删除 using 块并再次将 KeepAlive 放在方法的末尾,但它仍然抛出错误。
  • @agent-j 据我所知,我并没有明确地对代表做任何事情。我假设我正在使用的库内部发生了一些事情,那就是调用一个。我浏览了对象浏览器和在线指南,但遗憾的是,这个库的文档非常薄。

标签: c# .net r


【解决方案1】:

看起来像 R.NET 中的一个错误。您看到的异常发生在 .NET 层将回调传递给非托管代码但随后让委托进行垃圾收集时。我在您的重现代码中没有看到任何委托用法,因此得出的结论是它必须在 R.NET 中。

【讨论】:

  • 太好了,斯蒂芬 - 谢谢!你是对的,我没有打电话给任何类型的代表,虽然我不确定我是否在没有意识到的情况下这样做了。作为 C# 的新手,我不确定是不是我犯了错误。我将在我刚刚发现的 R.NET 论坛上发布此内容,并希望可以进行修复。干杯!
【解决方案2】:

正如斯蒂芬所建议的那样,事实证明这是我使用的 R.NET 版本中的一个错误,而不是我所做的错误(这是我最初的猜测,因此我在这里发帖的原因! )。 R.NET 的作者已经回复了我在 R.NET 论坛上的帖子,幸运的是已经解决了这个问题并更新了 R.NET,虽然还没有以 dll 的形式(导入源文件很容易)尽管)。

我可以确认最新版本的源文件实际上并没有遇到这个问题。欢呼!感谢所有在这里回复的人。很遗憾,我花了这么长时间来解决一个简单的错误,但它有助于在我寻找解决方案时了解更多 C# / .NET 知识。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    相关资源
    最近更新 更多