Я использую библиотеку с именем muParserNET в моем приложении. muParserNET - это библиотека парсинга функций, и мое приложение вызывает ее несколько раз из разных потоков.
muParserNET состоит из C ++ (неуправляемой) библиотеки DLL с управляемой оболочкой C #. В этой оболочке при инициализации он передает указатель на подпрограмму обработки ошибок в неуправляемую библиотеку.
т.е. внутри класса Parser у нас есть эта функция:
/// <summary>
/// Error handler. It loads the ParserError exception.
/// </summary>
private void ErrorHandler()
{
IntPtr ptrMessage = MuParserLibrary.mupGetErrorMsg(this.parserHandler);
string message = Marshal.PtrToStringAnsi(ptrMessage);
IntPtr ptrToken = MuParserLibrary.mupGetErrorToken(this.parserHandler);
string token = Marshal.PtrToStringAnsi(ptrToken);
string expr = this.Expr;
ErrorCodes code = (ErrorCodes)MuParserLibrary.mupGetErrorCode(this.parserHandler);
int pos = MuParserLibrary.mupGetErrorPos(this.parserHandler);
// lança a exceção
throw new ParserError(message, expr, token, pos, code);
}
Вот инициализация объекта анализатора в управляемом коде. это происходит в последней строке этой функции:
public Parser()
{
// inicializa o parser
this.parserHandler = MuParserLibrary.mupCreate(0);
// inicializa o dicionário com as variáveis
this.vars = new Dictionary<string, ParserVariable>();
// inicializa as listas de delegates
this.identFunctionsCallbacks = new List<ParserCallback>();
this.funcCallbacks = new Dictionary<string, ParserCallback>();
this.infixOprtCallbacks = new Dictionary<string, ParserCallback>();
this.postfixOprtCallbacks = new Dictionary<string, ParserCallback>();
this.oprtCallbacks = new Dictionary<string, ParserCallback>();
// inicializa o delegate de factory
this.factoryCallback = new ParserCallback(new IntFactoryFunction(this.VarFactoryCallback));
// ajusta a função de tratamento de erros
MuParserLibrary.mupSetErrorHandler(this.parserHandler, this.ErrorHandler);
}
При запуске этого кода, время от времени, при вызовах для оценки функций (поэтому иногда после инициализации объекта) я получаю эту ошибку:
A callback was made on a garbage collected delegate of type 'muParserNET!muParserNET.ErrorFuncType::Invoke'
ErrorFuncType - это тип this.ErrorHandler, переданный выше с использованием MuParserLibrary.mupSetErrorHandler.
Насколько я понимаю, поскольку функция обработчика ошибок не используется после того, как ее указатель передан в неуправляемый код, она получает сборщик мусора. Как я могу предотвратить это?
Дополнительная информация на основе первого ответа:
Объект синтаксического анализа создается внутри подпрограммы вычисления, которая обычно может выполняться одновременно до 8 отдельных потоков. Объект создается и удаляется в рамках процедуры расчета. По этой причине я не хотел создавать объект синтаксического анализа как статический, поскольку он ограничивал бы меня только одним потоком, использующим синтаксический анализатор одновременно.