我的应用程序提供 python 插件系统。为了从 c# 调用 python。我已经编写了嵌入 python dll 的 C 包装器。你可以在这里找到要点C wrapper gist。
然后我在 C# 中使用 P/Invoke 来调用 C dll。像这样:
[DllImport("PyWinAlfred.dll")] private extern static IntPtr ExecPython(string directory, string file, string query);
如果我没有在 C# 创建的多个线程中执行上述代码,那也没关系。问题是如果我不使用线程,c# 中的主线程将被阻塞,而 python 代码需要很长时间才能执行。
这是我使用的 C# 多线程代码:
ThreadPool.QueueUserWorkItem(状态 => { ExecPython(目录、文件、查询); });
因此,我尝试在 C 包装器代码中添加多线程支持。正如你在那个要点中看到的那样。我试图添加:
// 创建 GIL/启用线程 PyEval_InitThreads(); PyGILState_STATE gstate = PyGILState_Ensure(); //python代码 PyGILState_Release(gstate);
但这对我不起作用。当我创建一些线程来调用该 dll 时,我会得到一个异常。
我还尝试了以下代码。仍然没有工作。
PyThreadState* 状态 = PyThreadState_Get(); // 每个线程一次 PyThreadState* stateForNewThread = PyThreadState_New(state->interp); PyEval_RestoreThread(stateForNewThread); //python代码 PyEval_SaveThread();
我想知道这是否是因为我输入Py_Initialize();
了每个调用。当 thread2 执行时,Py_Initialize();
将清除 thread1 可能需要的所有信息。我试图Py_Initialize()
在我的应用程序启动时调用,所以它只会被调用一次。但是没有用。看起来这两个调用在 p/invoke 调用中是完全隔离的。
我在C和嵌入python方面很差,有人有相关经验吗?我的项目托管在https://github.com/qianlifeng/WinAlfred如果你们想看我上面描述的代码。