为什么从C#调用Python lambda表达式不是线程安全的?
我在IronPython中定义了一个无副作用(纯)lambda表达式,并将其分配给一个C#delegate。当从多个线程同时调用委托时,我会得到类型为AccessViolationException、NullReferenceException和FatalEngineeExecutionError的异常 错误的发生是不确定的,通常需要几百万次迭代才能引起,这对我来说就是“竞争条件”。我怎样才能避免呢 只有在使用x64(x86不会崩溃)在调试器外部运行进程时才会引发异常。测试系统是Windows7、.NETFramework 4.0和IronPython 2.7.1上的核心I7(8个线程) 以下是产生错误的最小代码:为什么从C#调用Python lambda表达式不是线程安全的?,c#,lambda,thread-safety,ironpython,C#,Lambda,Thread Safety,Ironpython,我在IronPython中定义了一个无副作用(纯)lambda表达式,并将其分配给一个C#delegate。当从多个线程同时调用委托时,我会得到类型为AccessViolationException、NullReferenceException和FatalEngineeExecutionError的异常 错误的发生是不确定的,通常需要几百万次迭代才能引起,这对我来说就是“竞争条件”。我怎样才能避免呢 只有在使用x64(x86不会崩溃)在调试器外部运行进程时才会引发异常。测试系统是Windows7
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(".");
}
var-engine=Python.CreateEngine();
双a=1.0;
双b=2.0;
while(true)
{
Func calculate=engine.Execute(“lambda,b:a+b”);
System.Threading.Tasks.Parallel.For(0,1000,=>
{
对于(inti=0;i<1000;i++){计算(a,b);}
});
控制台。写(“.”);
}
错误消息:
检测到FATAlexecutionEngineer错误
消息:运行时遇到致命错误。错误地址位于线程0x3da0上的0xf807829e。错误代码为0xc0000005。此错误可能是CLR或用户代码的不安全或不可验证部分中的错误。此错误的常见来源包括COM互操作或PInvoke的用户封送错误,这可能会损坏堆栈
更新:即使引擎声明为线程本地,它也会在一段时间后崩溃:
var calculate = new ThreadLocal<Func<double, double, double>>(() => Python.CreateEngine().Execute("lambda a,b : a+b"));
var calculate=newthreadlocal(()=>Python.CreateEngine().Execute(“lambda,b:a+b”);
您是否尝试过将64位数据类型(双精度)替换为32位数据类型(浮点)?我知道64位字段可能会有问题,这取决于处理器和代码。这看起来有点遥不可及,但值得一试。这可能是由于ScriptEngine中的竞争条件造成的。请注意,ScriptEngine.Execute返回对PythonFunction的引用,而不是Func(这是由于C#的动态行为,您可以将结果视为Func。我不是IronPython方面的专家,但查看PythonFunction的源代码,没有任何迹象表明它是线程安全的。运行类似的代码(见下文)在IronScheme上,不存在此类问题
我唯一能想到的是引擎。Execute(“lambda,b:a+b”)
创建一个解释函数而不是编译函数。将其与一个可能不安全的线程解释器相结合,然后使用kaboom
double a = 1.0;
double b = 2.0;
while (true)
{
var calculate = "(lambda (a b) (+ a b))".Eval<Callable>();
System.Threading.Tasks.Parallel.For(0, 1000, _ =>
{
for (int i = 0; i < 1000; i++) { calculate.Call(a, b); }
});
Console.Write(".");
}
双a=1.0;
双b=2.0;
while(true)
{
var calculate=“(lambda(ab)(+ab))”.Eval();
System.Threading.Tasks.Parallel.For(0,1000,=>
{
对于(inti=0;i<1000;i++){calculate.Call(a,b);}
});
控制台。写(“.”);
}
将double更改为float没有帮助。几百万次迭代
哪个循环是内部循环、并行循环还是while循环?