Мое приложение предоставляет систему плагинов python. Чтобы вызвать python из С#. Я написал C-оболочку для встраивания dll python. Вы можете найти суть здесь суть оболочки C.
Затем я использую P/Invoke в C# для вызова C dll. Нравится:
[DllImport("PyWinAlfred.dll")] private extern static IntPtr ExecPython(string directory, string file, string query);
Все в порядке, если я не выполнял приведенные выше коды в нескольких потоках, созданных C #. Проблема в том, что если я не использовал поток, основной поток в С# будет заблокирован, в то время как выполнение кода Python занимает много времени.
Вот код нескольких потоков С#, который я использую:
ThreadPool.QueueUserWorkItem(state => { ExecPython(directory,file,query); });
Итак, я попытался добавить поддержку нескольких потоков в код оболочки C. Как вы можете видеть в этой сути. Я попытался добавить:
// Create GIL/enable threads PyEval_InitThreads(); PyGILState_STATE gstate = PyGILState_Ensure(); //python codes PyGILState_Release(gstate);
Но это не работает для меня. Когда я создам несколько потоков для вызова этой dll, я получу исключение.
Я также пробовал следующие коды. Все еще не работает.
PyThreadState* state = PyThreadState_Get(); // Once in each thread PyThreadState* stateForNewThread = PyThreadState_New(state->interp); PyEval_RestoreThread(stateForNewThread); //python codes PyEval_SaveThread();
Мне было интересно, не потому ли это, что я добавляю Py_Initialize();
в каждый вызов. Когда поток2 выполнится, Py_Initialize();
очистит всю информацию, которая может потребоваться потоку1. Я пытался вызвать Py_Initialize()
при запуске моего приложения, поэтому оно будет вызываться только один раз. Но не сработало. Похоже, эти два вызова полностью изолированы в вызовах p/invoke.
Я плохо разбираюсь в C и встраиваю python, есть ли у кого-нибудь соответствующий опыт? Мой проект размещен в https://github.com/qianlifeng/WinAlfred. Если вы, ребята, хотите увидеть коды я описал выше.