我有几个用C编写的类,我想从使用Python for.NET的Python编写的应用程序中使用这些类。在
在以前使用Python4Delphi和Python的C API做过类似的事情之后,我知道对与Python交互的所有东西都保持全局解释器锁(GIL)是多么重要,同时在长时间运行的操作中释放它,以便其他Python线程可以运行。在
为了获得GIL,pythonfor.NET附带了方便的Py.GIL()
实用程序,我编写了NoGil
以使GIL的发布变得同样容易。在
我假设每当Python代码调用C#代码时,GIL会在调用期间保持不变。但是,似乎GIL不是在方法调用期间保存的,而是在构造函数调用期间保持的,如下面的示例所示。在
下面是C类和myNoGil
实用程序类,其中包含一些日志记录。为了简单起见,我没有完整地实现一次性模式。在
using Python.Runtime;
using System;
namespace PythonNet
{
public class Class1
{
public Class1()
{
using (new NoGil("constructor"))
{
Console.WriteLine("executing constructor");
}
}
public void Method()
{
using (new NoGil("method"))
{
Console.WriteLine("executing method");
}
}
}
public class NoGil: IDisposable
{
private string _message;
private IntPtr _state = IntPtr.Zero;
public NoGil(string message)
{
_message = message;
Console.WriteLine("Before calling BeginAllowThreads from " + message);
_state = PythonEngine.BeginAllowThreads();
Console.WriteLine("After calling BeginAllowThreads from " + _message);
}
public void Dispose()
{
if (_state == IntPtr.Zero)
{
Console.WriteLine("B_state == IntPtr.Zero in " + _message);
}
else
{
Console.WriteLine("Before calling EndAllowThreads from " + _message);
PythonEngine.EndAllowThreads(_state);
Console.WriteLine("After calling EndAllowThreads from " + _message);
}
}
}
}
它是从Python中使用的(在通过pip安装pythonnet包之后),如下所示:
^{pr2}$输出是
Before calling BeginAllowThreads from constructor
After calling BeginAllowThreads from constructor
executing constructor
Before calling EndAllowThreads from constructor
After calling EndAllowThreads from constructor
Before calling BeginAllowThreads from method
Fatal Python error: PyEval_SaveThread: NULL tstate
Current thread 0x0000124c (most recent call first):
File "test.py", line 5 in <module>
我用python2.7和3.6(都是64位的)进行了尝试,这是Python for.NET的最新版本2.3.0和.net4.0和4.6.1都是我的目标框架。在
问题:
目前没有回答
相关问题 更多 >
编程相关推荐