LINUX.ORG.RU

Как работать с потоками в UE4?

 , ,


0

1

Посоветуйте, пожалуйста, хороший пример по работе с потоками в рамках движка Unreal Engine 4. Также интересует как в потоке выводить отладочные сообщения, потому что в руководствах на оф сайте предупреждают чтобы не пользовались UE_LOG в потоке, а как тогда отлаживать?

Чем меня не устраивают существующие примеры? Они какие то невнятные, не компилируются, список хедеров почему-то убран в примерах (нахрена???). Я накатал простой пример, он компилируется, но намертво вешает UE4Editor.

Вот код: http://paste.org.ru/?vn3sqn Он у меня виснет, когда я делаю так:

void Atest::BeginPlay()
{
	thread.Init();
	thread.Run();
...

★★★★★

Последнее исправление: I-Love-Microsoft (всего исправлений: 1)

Не делай так :) А где у тебя код где ты используешь поток и условие выхода применяется? Поток спит секунду — каждую секунду :) Ну прога и спит форевер, пока не дернешь Stop(), если поток сам этого не делает никогда.

slackwarrior ★★★★★
()
Ответ на: комментарий от slackwarrior

Как не делать? Просто примера нормального нет перед глазами... Что-то максимально простое, как в документации Qt5 - там вообще как два байта переслать. А тут прям страдания какие-то.

Что будет запускать Run? Я должен просто Init вызвать, а Run сам запустится??? А как выводить отладочный текст в потоках?

I-Love-Microsoft ★★★★★
() автор топика
Ответ на: комментарий от I-Love-Microsoft

Как не делать? Просто примера нормального нет перед глазами...

Ну зделай чтоб Run чего-то делал кроме ожидания, например чего-то посчитал и вызвал себе Stop :) В отладке например посмотри, что там происходит. Если снаружи управлять — нужно логическую переменную или мутексом защищать или, как во втором примере, семафор накручивать (хотя это у них какие-то устаревшие привычки — как будто не было RAII или более удобных примитивов синхронизации чем семафор).

А тут прям страдания какие-то.

Ну, надо учитывать что про 2003 год это я тебе не просто так сказал :) Тяжелое наследие велосипедного плюсизма родом с оффтопика.

Что будет запускать Run? Я должен просто Init вызвать, а Run сам запустится???

У них тут немножк по-наркомански сделано (хотя раньше это «идиомой» кое-кто считали) — класс, в котором поток «физически» создается колом FRunnableThread::Create, передает «себя» (свои инстанс) в параметре этого кола (видишь там this?) Ну вот, поток, т.к. он уже создан, уже будет запускать Run() когда ты дернешь Init, т.е отдельно его (Run) дергать не надо, как тут и показано https://wiki.unrealengine.com/Multi-Threading:_How_to_Create_Threads_in_UE4#S...

Подробнее, чтоб понять чо как, можно в сорцах движка посмотреть — они доступны после регистрации.

Это все можно делать по-другому — т.е. «воркеры» эти не делать обертками потоков, а тупо задачами для поточного пула, в котором потокам пофиг кого «исполнять» — видимо с синхронизацией морочиться автор твоего примера не хотел, но тогда хотя бы надо что-то вроде точки ожидания в основном). И собственно пример использования всегда лучше искать, чтоб вопросов не возникало :)

А как выводить отладочный текст в потоках?

И кстати об отладке — хотя автор твоего примера пишет про то что логи использоват не айс, но он просто жопа ленивая — и не стал морочиться с синхронизацией — просто можно защитить лог примитивом синхронизации.

Тут чувак просто использует Glog->Log() и не трахает себе моск, т.к. поток один:

https://orfeasel.com/implementing-multithreading-in-ue4/

Но у UE4 не один способ делать асинхронные задачи, может тебе подойдет:

https://wiki.unrealengine.com/Using_AsyncTasks

или

https://wiki.unrealengine.com/Multi-Threading:_Task_Graph_System

Если «просто потоки» — тогда копай в сторону синхронизаций, пулов и т.д. (возможно что-то придется написать самому, просто чтоб удобнее было).

И общее правило буравчика — хорошо подумать, нужны ли потоки под твою задачу, т.к. UE4 сам не сильно поточный, особенно для блю-принтов https://global.gotomeeting.com/join/671646925 :)

А тут написано где собственно блокировка происходит естественным путем: https://docs.unrealengine.com/en-us/Programming/Rendering/ThreadedRendering

Ну вощем, раскопки в сорцах наиболее полезные в смысле понять чо-как энивей, т.к. кулстори индусов, которые пишут примеры скорее надо проверять, чем доверять.

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 1)
Ответ на: комментарий от slackwarrior

Благодарю, сенсэй! ^_^

Очень подробный полезный ответ.

Буду всё это внимательно изучать, перечитывать, вникать. В Qt5 конечно проще с потоками, но я справлюсь, должен справиться, программист я или хвост собачий? :)

I-Love-Microsoft ★★★★★
() автор топика
Ответ на: комментарий от slackwarrior

У меня работает отладка в потоке без всяких блокировок. Понимаю что это не безопасно и чревато крэшами, но могу ли я использовать это без mutex на время отладки а затем убрать их из кода полностью? Мне видится что можно, но «в продакшен» такое попасть не должно.

Можно еще класс сделать специальный, при входе в метод которого будет закрываться mutex.

При работе через Sleep там действительно появляется отладка в консоли через соответствующие времена, основной поток отрисовки не тормозит. Тема решена, хотя многое еще предстоит освоить, но оно хоть заработало и не виснет, действительно архаичная архитектура потоков...

Мне нужен именно «вечный» поток, у него нет условия завершения, разве что EndPlay.

I-Love-Microsoft ★★★★★
() автор топика

руководствах на оф сайте предупреждают чтобы не пользовались UE_LOG в потоке, а как тогда отлаживать?

отладить и потом убрать UE_LOG из кода, очевидно?

darkenshvein ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Можно еще класс сделать специальный, при входе в метод которого будет закрываться mutex.

У них есть уже :) FScopeLock Либо авторы примеров об нем не знают, либо примеры стухли.

Понимаю что это не безопасно и чревато крэшами, но могу ли я использовать это без mutex на время отладки а затем убрать их из кода полностью? Мне видится что можно, но «в продакшен» такое попасть не должно.

Ну никто не запретит же. Можешь конечно :) В крайнем случае можно свой логгер на коленке написать всегда, который тупо для одного потока будет файлик писать :)

Мне нужен именно «вечный» поток, у него нет условия завершения, разве что EndPlay.

Ну ващет этот «вечный» должен корректно завершаться при завершении приложения. Либо ему как-то просигналить надо в точке проверки завершения (ну, если специфичный для движка API-потоков такое умеет сам — см. в сторону https://api.unrealengine.com/INT/API/Runtime/Core/HAL/FRunnableThread/WaitFor...), либо тупо «силовыми методами» лочить и выставлять флаг на остановку.

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.