IronPythonで副作用のない(純粋な)ラムダ式を定義し、それをC#デリゲートに割り当てます。デリゲートを複数のスレッドから同時に呼び出すと、タイプの例外が発生します。アクセシビリティ例外、NullReferenceExceptionおよびFatalEngineExecutionError。なぜC#のPythonラムダ式をスレッドセーフではないと呼びますか?
エラーの発生は非決定論的であり、それを誘発するために大部分は数百万回の反復が必要となります。これは私にとって「競合状態」です。どうすればそれを避けることができますか?
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(".");
}
エラーメッセージ:
FatalExecutionEngineError was detected
Message: The runtime has encountered a fatal error. The address of the error was at 0xf807829e, on thread 0x3da0. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
アップデート:エンジンはスレッドローカルとして宣言されている場合でも、それはいくつかの時間後にクラッシュ:
はここでエラーを生成するために、最小限のコードです
var calculate = new ThreadLocal<Func<double, double, double>>(() => Python.CreateEngine().Execute("lambda a,b : a+b"));
'数百万どのループの反復?インナー、パラレル、またはその間? – leppie