Я определяю лямбда-выражение без побочных эффектов (чистый) в IronPython и назначаю его делегату C #.При одновременном вызове делегата из нескольких потоков я получаю исключения типа AccessViolationException , NullReferenceException и FatalEngineExecutionError .
Возникновение ошибки не-детерминированный, и для его провоцирования требуется несколько миллионов итераций, что говорит мне о «состоянии гонки».Как я могу избежать этого?
Исключения возникают только при запуске процесса с x64 (x86 не падает) и вне отладчика.Тестовая система - Core I7 (8 потоков) в Windows 7, .NET Framework 4.0 и IronPython 2.7.1.
Ниже приведен минимальный код для выдачи ошибки:
var engine = Python.CreateEngine();
double a = 1.0;
double b = 2.0;
while (true)
{
Func<double, double, double> calculate = engine.Execute("lambda a,b : a+b");
System.Threading.Tasks.Parallel.For(0, 1000, _ =>
{
for (int i = 0; i < 1000; i++) { calculate(a,b); }
});
Console.Write(".");
}
Ошибкасообщение:
Обнаружена ошибка FatalExecutionEngineEr *
Сообщение: во время выполнения обнаружена фатальная ошибка.Адрес ошибки был 0xf807829e, в потоке 0x3da0.Код ошибки 0xc0000005.Эта ошибка может быть ошибкой в CLR или в небезопасных или не поддающихся проверке частях пользовательского кода.Распространенные источники этой ошибки включают в себя ошибки пользовательского маршалинга для COM-взаимодействия или PInvoke, которые могут повредить стек.
Обновление: даже если ядро объявлено как локальное для потока, через некоторое время происходит сбой:
var calculate = new ThreadLocal<Func<double, double, double>>(() => Python.CreateEngine().Execute("lambda a,b : a+b"));