Тяжелая фоновая задача как общий объект в колбе [дубликат]

Если мы рассмотрим общие сценарии, в которых может быть выбрано это исключение, доступ к свойствам с объектом вверху.

Пример:

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
8
задан ildjarn 4 November 2011 в 19:04
поделиться

1 ответ

Что вы используете, это глобальная блокировка интерпретатора 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();

    ...
}
16
ответ дан fireant 25 August 2018 в 23:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: