Rau*_*otz 28 c# lambda ironpython thread-safety
我在IronPython中定义了一个无副作用(纯)lambda表达式,并将其分配给C#委托.当从多个线程同时调用委托时,我得到类型为AccessViolationException,NullReferenceException和FatalEngineExecutionError的异常.
错误的发生是非确定性的,并且它主要需要数百万次迭代来激发它,这对我说"竞争条件".我怎么能避免呢?
只有在使用x64(x86不崩溃)并且在调试器之外运行进程时才会引发异常.测试系统是Windows 7,.NET Framework 4.0和IronPython 2.7.1上的Core I7(8个线程).
这是产生错误的最小代码:
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(".");
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
检测到FatalExecutionEngineError
消息:运行时遇到致命错误.错误的地址是0xf807829e,位于线程0x3da0上.错误代码是0xc0000005.此错误可能是CLR中的错误,也可能是用户代码的不安全或不可验证部分中的错误.此错误的常见来源包括COM-interop或PInvoke的用户编组错误,这可能会破坏堆栈.
更新:即使引擎声明为线程本地,它会在一段时间后崩溃:
var calculate = new ThreadLocal<Func<double, double, double>>(() => Python.CreateEngine().Execute("lambda a,b : a+b"));
Run Code Online (Sandbox Code Playgroud)
您是否尝试过用 32 位数据类型(浮点型)替换 64 位数据类型(双精度型)?我确实知道“对 32 位或更少的字段进行简单的读取或写入始终是原子的”,而 64 位字段可能会出现问题,具体取决于处理器和代码。这似乎是一个遥远的尝试,但值得一试。
| 归档时间: |
|
| 查看次数: |
1032 次 |
| 最近记录: |