Подтвердить что ты не робот

Прекращение сбора мусора для неуправляемого делегата

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

У меня не было проблем с простыми базовыми командами. Я сделал простой калькулятор и что-то импортировать данные в сетку данных. Но теперь я продолжаю получать следующую ошибку:

Обратный вызов был сделан на сборщике мусора типа "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() (без везения), а также создание частного поля в отдельном классе, от которого нельзя избавиться. К сожалению, это тоже не сработало.

Есть ли что-нибудь еще, что я могу попробовать? Я очень, очень новичок в С#, поэтому я был бы признателен за любые указания о том, как это сделать. Я очень полагаю, что мой недостаток в успехе с предложенными методами либо связан с (1) моими собственными ошибками в реализации стандартных исправлений (это кажется наиболее вероятным), либо (2) причудой, связанной с R.NET, что я Понятно.

Любая помощь будет принята с благодарностью!

4b9b3361

Ответ 1

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

Ответ 2

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

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