#c# #r #r.net
#c# #r #r.net
Вопрос:
Я использую R.Net и пакеты R.Net.Community в моем проекте c #, чтобы включить R script. У меня есть класс c # следующим образом:
foreach(var item in list)
{
callR(item);
}
и метод в другом классе для запуска R script:
CallR(int item)
{
//init the R engine
REngine.SetEnvironmentVariables();
engine = REngine.GetInstance();
engine.Initialize();
//Perform R
engine.SetSymbol("data", item);
engine.Evaluate("data<-data*data");
//engine.dispose
//Cannot use engine.dispose as re initialization of engine then, is not possible
}
Редактировать
У меня есть еще один третий класс, который вызывает тот же метод R. Если я создам его экземпляр в классе, в котором я создал цикл, то как использовать эту инициализацию в этом классе?
Проблема: этот код отлично работает локально, однако при его развертывании на сервере он прерывается и выдает исключение: «Не удалось загрузить статистику библиотеки».
При более глубоком поиске я нашел это, в котором говорится, что многократная инициализация Rengine вызывает эту проблему.
Поэтому мой вопрос заключается в том, как инициализировать Rengine при запуске самого приложения только один раз и использовать его экземпляр в сценариях, подобных моему коду выше?
Ответ №1:
Я думаю, что лучшей практикой было бы использовать однотонный шаблон, что-то вроде этого:
public class RNetEngine : IDisposable
{
private bool _disposed;
private REngine _rEngine;
private static readonly object Lock = new object();
private REngine Engine
{
get
{
if (_rEngine == null)
{
lock (Lock)
{
if (_rEngine == null)
{
_rEngine = REngine.GetInstance();
}
}
}
return _rEngine;
}
}
public void Evaluate(string expression)
{
Engine.Evaluate(expression);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
if (_rEngine != null amp;amp; !_rEngine.Disposed)
{
_rEngine.Dispose();
}
}
_disposed = true;
}
}
Это обеспечит потокобезопасность и утилизацию при необходимости. Я использовал это с Castle.Виндзорский одноэлементный образ жизни, поэтому он не статичен.
Комментарии:
1. Я ценю ваш ответ, но я думаю, что после удаления REngine не может быть повторно инициализирован. Источник: author-entry17.rssing.com/chan-9456546/all_p63.html
2. Правильно, но поскольку это однотональный файл, он не будет удален во время работы приложения, и после этого вам нужно освободить использованные ресурсы.
3. О, хорошо, я не знал об этом .. Спасибо за помощь. Обязательно попробую.
Ответ №2:
Вы можете изменить класс CallR, чтобы иметь один экземпляр класса REngine и получать его с помощью метода, который инициализирует его только один раз, например
public static REngine engine = null;
public static REngine GetInitiazedREngine()
{
if (engine==null)
{
REngine.SetEnvironmentVariables();
engine = REngine.GetInstance();
engine.Initialize();
}
return engine;
}
CallR(int item)
{
//Get the initialized R Engine
REngine initializedEngine=GetInitiazedREngine();
//Perform R
initializedEngine.SetSymbol("data", item);
initializedEngine.Evaluate("data<-data*data");
//engine.dispose
//Cannot use engine.dispose as re initialization of engine then, is not possible
}