Unreal Engine has a useful feature called AsyncTask that allows you to execute code asynchronously. It functions by running specific code on a specified thread and is primarily used when the task is too heavy to be executed instantly without blocking the game thread.

It also provides a solution to issues arising from multithreading, particularly accessing properties from one thread that are intended to be used and/or modified in another thread. 1

AsyncTask(ENamedThreads::AnyThread, []()
{
	// This code will run asynchronously, without freezing the game thread
});

You can also create nested calls to asynchronous tasks, for example:

AsyncTask(ENamedThreads::AnyThread, []()
{
	// This code will run asynchronously, without freezing the game thread
		
	AsyncTask(ENamedThreads::GameThread, []()
	{
		// This code will be executed on the game thread
	});
});

You can also combine this with delegates and execute your code asynchronously with Blueprints
#include "Async/Async.h"

DECLARE_DYNAMIC_DELEGATE_OneParam(FAsyncDelegateExample, const TArray<float>&, OutData);

// Class, meta, etc

UFUNCTION(BlueprintCallable)
static void AddNumbersAsync(TArray<float> InData, const FAsyncDelegateExample& Result)
{
	AsyncTask(ENamedThreads::AnyThread, [InData = MoveTemp(InData), Result]() mutable
	{
		// Just for example
		for (float& InDataElement : InData)
		{
			InDataElement += 10;
		}

		AsyncTask(ENamedThreads::GameThread, [OutData = MoveTemp(InData), Result]() mutable
		{
			Result.ExecuteIfBound(OutData);
		});
	});
}

Async BP example


  1. It is known that it is not safe to access an object from one thread while it is being modified in another thread without using synchronization techniques such as mutexes . However, some engine-specific code lacks these thread synchronization features, so the only safe way to access these objects is to access them from the desired thread. It’s also important to note that while the GameThread has a single assigned thread, using AnyThread, AnyHiPriThreadHiPriTask, etc. don’t have a fixed assigned thread and are obtained based on the available ones. ↩︎