Если мы рассмотрим общие сценарии, в которых может быть выбрано это исключение, доступ к свойствам с объектом вверху.
Пример:
string postalcode=Customer.Address.PostalCode;
//if customer or address is null , this will through exeption
здесь, если адрес имеет значение null, то вы получите NullReferenceException.
Итак, в качестве практики мы всегда должны использовать проверку нуля, прежде чем обращаться к свойствам в таких объектах (особенно в общих)
string postalcode=Customer?.Address?.PostalCode;
//if customer or address is null , this will return null, without through a exception
Что вы используете, это глобальная блокировка интерпретатора python. GIL позволяет только один поток запускать в интерпретаторе python.
Одним из преимуществ Boost.Python является то, что вы можете освободить GIL, сделать C ++, а затем вернуть его, когда закончите. Это также несет ответственность. Python обычно выпускает GIL через регулярные промежутки времени, чтобы дать другим потокам возможность запускать. Если вы находитесь на C ++, это ваша работа. Если вы продолжаете хруст в течение 2 часов, удерживая GIL, вы заморозите весь интерпретатор.
Это можно легко исправить с помощью небольшого обратного RAII:
class releaseGIL{
public:
inline releaseGIL(){
save_state = PyEval_SaveThread();
}
inline ~releaseGIL(){
PyEval_RestoreThread(save_state);
}
private:
PyThreadState *save_state;
};
Теперь вы можете изменить свой код так:
class Foo{
public:
Foo(){}
void run(){
{
releaseGIL unlock = releaseGIL();
int seconds = 2;
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
}
};
ОЧЕНЬ важно отметить, что вы НЕ ДОЛЖНЫ касаться какого-либо кода на основе питона или данных python или обращаться к интерпретатору, не удерживая GIL. Это приведет к сбою вашего интерпретатора.
Также можно пойти в другую сторону. Нить, в настоящее время не содержащая GIL, может получить ее и выполнить вызовы на python. Это может быть поток, который ранее выпускал GIL, или тот, который начинался на c ++ и никогда не имел GIL. Вот для этого класс RAII:
class AcquireGIL
{
public:
inline AcquireGIL(){
state = PyGILState_Ensure();
}
inline ~AcquireGIL(){
PyGILState_Release(state);
}
private:
PyGILState_STATE state;
};
Использование осталось в качестве упражнения для ученика.
Дополнительная заметка (я всегда забываю упомянуть об этом):
Если вы собираетесь возиться с GIL в c ++, ваше определение модуля должно начинаться с этого кода:
BOOST_PYTHON_MODULE(ModuleName)
{
PyEval_InitThreads();
...
}