Skip to content

Instantly share code, notes, and snippets.

Last active March 24, 2023 05:15
What would you like to do?
Long Running Async Lambdas, lock-free (UE4)
//Convenience Wrapper functions
//Using TaskGraph
FGraphEventRef RunLambdaOnGameThread(TFunction< void()> InFunction)
return FFunctionGraphTask::CreateAndDispatchWhenReady(InFunction, TStatId(), nullptr, ENamedThreads::GameThread);
FGraphEventRef RunLambdaOnAnyThread(TFunction< void()> InFunction)
return FFunctionGraphTask::CreateAndDispatchWhenReady(InFunction, TStatId(), nullptr, ENamedThreads::AnyThread);
//Uses proper threading, for any task that may run longer than about 2 seconds.
void RunLongLambdaOnAnyThread(TFunction< void()> InFunction)
//Example use case
//Run your code
RunLongLambdaOnAnyThread([] {
//Your off-thread code here, if you access data here, make sure you make an immutable copy (e.g. const)
//Assume you got some results you want to pass back
FString someResults = FString(TEXT("some data results"));
//copy data
const FString safeResultString = someResults
//pass results back to game thread
RunLambdaOnGameThread([pathString] {
//Do something with your results
#pragma once
#include "ZipUtilityPrivatePCH.h"
#include "LambdaRunnable.h"
uint64 FLambdaRunnable::ThreadNumber = 0;
FLambdaRunnable::FLambdaRunnable(TFunction< void()> InFunction)
FunctionPointer = InFunction;
Finished = false;
Number = ThreadNumber;
FString threadStatGroup = FString::Printf(TEXT("FLambdaRunnable%d"), ThreadNumber);
Thread = FRunnableThread::Create(this, *threadStatGroup, 0, TPri_BelowNormal); //windows default = 8mb for thread, could specify more
delete Thread;
Thread = NULL;
bool FLambdaRunnable::Init()
//UE_LOG(LogClass, Log, TEXT("FLambdaRunnable %d Init"), Number);
return true;
uint32 FLambdaRunnable::Run()
if (FunctionPointer)
//UE_LOG(LogClass, Log, TEXT("FLambdaRunnable %d Run complete"), Number);
return 0;
void FLambdaRunnable::Stop()
Finished = true;
void FLambdaRunnable::Exit()
Finished = true;
//UE_LOG(LogClass, Log, TEXT("FLambdaRunnable %d Exit"), Number);
//delete ourselves when we're done
delete this;
void FLambdaRunnable::EnsureCompletion()
FLambdaRunnable* FLambdaRunnable::RunLambdaOnBackGroundThread(TFunction< void()> InFunction)
FLambdaRunnable* Runnable;
if (FPlatformProcess::SupportsMultithreading())
Runnable = new FLambdaRunnable(InFunction);
//UE_LOG(LogClass, Log, TEXT("FLambdaRunnable RunLambdaBackGroundThread"));
return Runnable;
return nullptr;
#pragma once
Long duration lambda wrapper, which are generally not supported by the taskgraph system. New thread per lambda and they will auto-delete upon
class FLambdaRunnable : public FRunnable
/** Thread to run the worker FRunnable on */
FRunnableThread* Thread;
uint64 Number;
//Lambda function pointer
TFunction< void()> FunctionPointer;
/** Use this thread-safe boolean to allow early exits for your threads */
FThreadSafeBool Finished;
//static TArray<FLambdaRunnable*> Runnables;
static uint64 ThreadNumber;
//~~~ Thread Core Functions ~~~
//Constructor / Destructor
FLambdaRunnable(TFunction< void()> InFunction);
virtual ~FLambdaRunnable();
// Begin FRunnable interface.
virtual bool Init();
virtual uint32 Run();
virtual void Stop();
virtual void Exit() override;
// End FRunnable interface
/** Makes sure this thread has stopped properly */
void EnsureCompletion();
Runs the passed lambda on the background thread, new thread per call
static FLambdaRunnable* RunLambdaOnBackGroundThread(TFunction< void()> InFunction);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment