停止非托管代理的垃圾收集

时间:2011-06-26 16:37:51

标签: c# .net r

我最近一直在尝试使用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相关的怪癖不明白。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:2)

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

我可以确认最新版本的源文件确实没有遇到这个问题。欢呼!感谢所有在这里回复的人。不幸的是,我花了很长时间在一个简单的bug上摸不着头脑,但是在我寻找解决方案时,它有助于了解更多C#/ .NET内容。