C++ Вопрос HTTP запрос фризит основной поток

I love C++
Пользователь
Статус
Оффлайн
Регистрация
26 Мар 2021
Сообщения
218
Реакции[?]
46
Поинты[?]
1K
Здравствуйте. При отправке запроса зависает основной поток игры. Как сделать асинхронный HTTP запрос чтобы не зависала игра.
Пробовал std::thread.detach но результат не получить. Для запросов использовал библиотеку libcpr
 
Начинающий
Статус
Оффлайн
Регистрация
22 Ноя 2022
Сообщения
7
Реакции[?]
3
Поинты[?]
0
Делай асинхронный запрос. В документации этой либы есть примеры:
Пожалуйста, авторизуйтесь для просмотра ссылки.
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
I love C++
Пользователь
Статус
Оффлайн
Регистрация
26 Мар 2021
Сообщения
218
Реакции[?]
46
Поинты[?]
1K
Делай асинхронный запрос. В документации этой либы есть примеры:
Пожалуйста, авторизуйтесь для просмотра ссылки.
Пожалуйста, авторизуйтесь для просмотра ссылки.
Я смотрел это и пробовал, но как Вы понимаете мне это не помогло, std::future все равно фризит поток до завершения потока.
 
Забаненный
Статус
Оффлайн
Регистрация
2 Мар 2021
Сообщения
1,083
Реакции[?]
406
Поинты[?]
1K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Здравствуйте. При отправке запроса зависает основной поток игры. Как сделать асинхронный HTTP запрос чтобы не зависала игра.
Пробовал std::thread.detach но результат не получить. Для запросов использовал библиотеку libcpr
а как же CreateThread?
 
Начинающий
Статус
Оффлайн
Регистрация
22 Ноя 2022
Сообщения
7
Реакции[?]
3
Поинты[?]
0
I love C++
Пользователь
Статус
Оффлайн
Регистрация
26 Мар 2021
Сообщения
218
Реакции[?]
46
Поинты[?]
1K
Забаненный
Статус
Оффлайн
Регистрация
2 Мар 2021
Сообщения
1,083
Реакции[?]
406
Поинты[?]
1K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Крашит у меня, может не правильно аргументы в поток передаю. Если предоставишь рабочий пример, буду благодарен.
CreateThread(0, 0 (LPTHREAD_START_ROUTINE)/*function name*/, 0, 0, 0, 0);
 
IRQL_APC_LEVEL
Пользователь
Статус
Оффлайн
Регистрация
25 Авг 2018
Сообщения
211
Реакции[?]
88
Поинты[?]
3K
Это понятно, но как правильно передать аргументы в поток?
У CreateThread есть аргумент "LPVOID lpParameter". В него нужно передать указатель на аргумент(ы), которые ты хочешь получить в функции, на которую создаешь поток. Сама функция должна иметь вид function_name(LPVOID lpArgs)

Выглядеть будет +- так: CreateThread(NULL, 0 (LPTHREAD_START_ROUTINE)YourFunction, lpSomeData, 0, NULL);
 
I love C++
Пользователь
Статус
Оффлайн
Регистрация
26 Мар 2021
Сообщения
218
Реакции[?]
46
Поинты[?]
1K
У CreateThread есть аргумент "LPVOID lpParameter". В него нужно передать указатель на аргумент(ы), которые ты хочешь получить в функции, на которую создаешь поток. Сама функция должна иметь вид function_name(LPVOID lpArgs)

Выглядеть будет +- так: CreateThread(NULL, 0 (LPTHREAD_START_ROUTINE)YourFunction, lpSomeData, 0, NULL);
Сделал все работает вроде как нужно. Но появилась другая проблема, скорее всего побочка от этого. Когда выгружаю dll то крашит игру. Провёл тесты выяснил что крашит из-за того что возвращаю результат из потока. Конечно синхронизировал поток с помощью mutex.

C++:
uint32_t ThreadResponse(LPVOID _AsyncData)
{
    try {
        mutex Mtx{};

        Mtx.lock();
        stAsyncData* AsyncData = reinterpret_cast<stAsyncData*>(_AsyncData);
        AsyncData->_Response = cpr::Get(AsyncData->_Url);
        Mtx.unlock();

        return 0;
    }
    catch (const exception& Error) {
        cout << "Exception AsyncRequest: " << Error.what() << endl;
    }
}
 
I love C++
Пользователь
Статус
Оффлайн
Регистрация
26 Мар 2021
Сообщения
218
Реакции[?]
46
Поинты[?]
1K
Сделал все работает вроде как нужно. Но появилась другая проблема, скорее всего побочка от этого. Когда выгружаю dll то крашит игру. Провёл тесты выяснил что крашит из-за того что возвращаю результат из потока. Конечно синхронизировал поток с помощью mutex.

C++:
uint32_t ThreadResponse(LPVOID _AsyncData)
{
    try {
        mutex Mtx{};

        Mtx.lock();
        stAsyncData* AsyncData = reinterpret_cast<stAsyncData*>(_AsyncData);
        AsyncData->_Response = cpr::Get(AsyncData->_Url);
        Mtx.unlock();

        return 0;
    }
    catch (const exception& Error) {
        cout << "Exception AsyncRequest: " << Error.what() << endl;н
    }
}
Прикол получается, я просто создал поток через std::thread(func).detach() и в функцию засунул бесконечный цикл. Оно все равно крашит, получается дело в потоке, а не в коде выше... Хз что с потоком делать чтобы выгружать его нормально
 
Начинающий
Статус
Оффлайн
Регистрация
22 Ноя 2022
Сообщения
7
Реакции[?]
3
Поинты[?]
0
1. Не понял пока зачем тут нужен mutex, но да ладно, пусть будет. Но ты неправильно тут юзаешь mutex. Ты каждый вызов функции создаешь новый локальный mutex, это не имеет смысла. Должен быть один общий mutex на все вызовы, тогда и блокировка будет корректно работать по этому mutex'у.
2. Непонятно зачем ты сразу делаешь detach(). Ты таким образом ничего не получаешь кроме потери контроля над потоком. Попробуй наоборот, контролировать поток до конца. Создай хранилище указателей на созданные потоки и только при detach’е либы убедись что все они завершены.

C++:
// Допустим есть статичное хранилище потоков, с его инициализацией думаю разберешься
static std::vector<std::thread*> my_threads;

// ...

// создавай потоки так
my_threads.push_back(new std::thread(func));

// ...

// при выгрузке либы делай так
// пока в хранилище есть потоки
while(!my_threads.empty())
{
    // получаем какой-то поток
    auto th = my_threads.back();
    
    // ждем его завершения
    th->join();
    
    // удаляем объект потока
    delete th;
    
    // удаляем из хранилища
    my_threads.pop_back();
}
По идее все join'ы должны почти без блокировки закрываться, если все http запросы в потоках завершились нормально и не остались висеть.
 
I love C++
Пользователь
Статус
Оффлайн
Регистрация
26 Мар 2021
Сообщения
218
Реакции[?]
46
Поинты[?]
1K
1. Не понял пока зачем тут нужен mutex, но да ладно, пусть будет. Но ты неправильно тут юзаешь mutex. Ты каждый вызов функции создаешь новый локальный mutex, это не имеет смысла. Должен быть один общий mutex на все вызовы, тогда и блокировка будет корректно работать по этому mutex'у.
2. Непонятно зачем ты сразу делаешь detach(). Ты таким образом ничего не получаешь кроме потери контроля над потоком. Попробуй наоборот, контролировать поток до конца. Создай хранилище указателей на созданные потоки и только при detach’е либы убедись что все они завершены.

C++:
// Допустим есть статичное хранилище потоков, с его инициализацией думаю разберешься
static std::vector<std::thread*> my_threads;

// ...

// создавай потоки так
my_threads.push_back(new std::thread(func));

// ...

// при выгрузке либы делай так
// пока в хранилище есть потоки
while(!my_threads.empty())
{
    // получаем какой-то поток
    auto th = my_threads.back();
   
    // ждем его завершения
    th->join();
   
    // удаляем объект потока
    delete th;
   
    // удаляем из хранилища
    my_threads.pop_back();
}
По идее все join'ы должны почти без блокировки закрываться, если все http запросы в потоках завершились нормально и не остались висеть.
Спасибо, я учту твой пример. Вкратце скажу зачем это все мне нужно. Я делаю софт в котором хочу прикрутить Телеграм-Уведомление и управление в том числе. Обработчик сообщений и функции отправки сообщения сделать не составило труда, проблема состоялась в том что это все вызывается в хуке игры или Present что означает при отправке HTTPS запроса фризилась игра(проседал fps).
 
Сверху Снизу