Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么从C#调用Python lambda表达式不是线程安全的?_C#_Lambda_Thread Safety_Ironpython - Fatal编程技术网

为什么从C#调用Python lambda表达式不是线程安全的?

为什么从C#调用Python lambda表达式不是线程安全的?,c#,lambda,thread-safety,ironpython,C#,Lambda,Thread Safety,Ironpython,我在IronPython中定义了一个无副作用(纯)lambda表达式,并将其分配给一个C#delegate。当从多个线程同时调用委托时,我会得到类型为AccessViolationException、NullReferenceException和FatalEngineeExecutionError的异常 错误的发生是不确定的,通常需要几百万次迭代才能引起,这对我来说就是“竞争条件”。我怎样才能避免呢 只有在使用x64(x86不会崩溃)在调试器外部运行进程时才会引发异常。测试系统是Windows7

我在IronPython中定义了一个无副作用(纯)lambda表达式,并将其分配给一个C#delegate。当从多个线程同时调用委托时,我会得到类型为AccessViolationExceptionNullReferenceExceptionFatalEngineeExecutionError的异常

错误的发生是不确定的,通常需要几百万次迭代才能引起,这对我来说就是“竞争条件”。我怎样才能避免呢

只有在使用x64(x86不会崩溃)在调试器外部运行进程时才会引发异常。测试系统是Windows7、.NETFramework 4.0和IronPython 2.7.1上的核心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(".");   
}
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循环?