Остановка сбора мусора для неуправляемого делегата - PullRequest
16 голосов
/ 26 июня 2011

Я недавно пытался использовать 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 ]

7 голосов
/ 26 июня 2011

Похоже, ошибка в R.NET.Исключение, которое вы видите, происходит, когда уровень .NET передает обратный вызов неуправляемому коду, но затем позволяет делегату собирать мусор.Я не вижу использования делегата в вашем коде repro, отсюда вывод, что он должен быть в R.NET.

2 голосов
/ 28 июня 2011

Как предположил Стивен, оказалось, что это была ошибка в версии R.NET, которую я использовал, а не ошибка в том, что я делал (это было мое первоначальное предположение, отсюда и причина для публикации здесь! ). Автор R.NET ответил на мой пост на форумах R.NET и, к счастью, уже решил эту проблему и обновил R.NET, хотя пока не в виде dll (достаточно легко импортировать исходные файлы хоть).

Я могу подтвердить, что последняя версия исходных файлов на самом деле не страдает от этой проблемы. Ура! Спасибо всем, кто ответил здесь. К сожалению, я потратил так много времени на то, чтобы почесать голову над простой ошибкой, но это помогло мне узнать больше о C # / .NET, пока я искал решение.

...