Hi Mathias,
Thanks for sharing this. I’ve narrowed it down to this using the new task API.
It boils down to a background priority task having a normal priority task as its prerequisite.
`UE::Tasks::FTask Task =
UE::Tasks::Launch(
TEXT(“Task”),
{ FPlatformMisc::LowLevelOutputDebugStringf(TEXT(“Subsequent Task\n”)); },
UE::Tasks::Launch(TEXT(“Task”), { FPlatformMisc::LowLevelOutputDebugStringf(TEXT(“Initial Task\n”)); }),
LowLevelTasks::ETaskPriority::BackgroundNormal
);
while (!Task.IsCompleted())
{
}`It’s generally not very good for performance to have long series of tasks ping-ponging between priorities like in your example. But obviously, this is a bug in the taskgraph that’s we’ll fix. I’ll let you know as soon as there is a CL to fix this.
In the meantime, you can try this simple change and confirm to us if it fixes your issue.
In TaskPrivate.h, change the Close() implementation to always wake up a worker.
It will bypasses an optimization where we schedule the next subsequent to be run by the same thread. In this case, the condition is wrong because the thread executing the task is a normal thread, and the subsequent is a background task so it cannot be executed by the current thread and we need to wake up another one instead.
Ideally, the final fix should preserve the optimization, but will need to be aware of tasks priorities.
`void Close()
{
TASKGRAPH_VERBOSE_EVENT_SCOPE(FTaskBase::Close);
checkSlow(!IsCompleted());
// Push the first subsequent to the local queue so we pick it up directly as our next task.
// This saves us the cost of going to the global queue and performing a wake-up.
// But if we’re a task event, always wake up new workers because the current task could continue executing for a long time after the trigger.
// BEGIN EDIT
bool bWakeUpWorker = true; //ExtendedPriority == EExtendedTaskPriority::TaskEvent;
// END EDIT`Ideally, the final fix should preserve the optimization, but will need to be aware of tasks priorities.
Thanks
Danny