What is supposed to prevent TickAsyncThread from running while garbage collection runs?

I am seeing an ensure failure stating that:

Assertion failed: !IsGarbageCollecting() [File:X:\J\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp] [Line: 2790] Unable to create new object: StaticMeshComponent <name removed for privacy> Creating UObjects while Collecting Garbage is not allowed!

It seems to me that there should be a test to make sure garbage collection is not running before you call QueueEvent_ProcessImportsAndExports() in ConditionalQueueProcessImportsAndExports. But perhaps I’m missing something. I suppose there could also be a lock invoked on garbage collection to prevent this issue. Not sure where that lock should be set though. This ensure is being invoked from

FAsyncLoadingThread::TickAsyncThread()

Ultimately I guess the question is, Is this a bug in the unreal code, or are we somehow invoking an async load when one shouldn’t be done? If the latter, what control would we use to supress loads during the garbage collection? Thanks for any help you can provide.

I don’t think it’s a bug, but I find it very confusing. Used to be you couldn’t use NewObject at all in any except the game thread. Then this has changed, so now you can, but you can’t create a NewObject while GC is running. Here’s basically how I handle the situation and it seems to work very well, thus far:

void UMyClass::MyFunction() {
    AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [&, OnCompleted]() {
        while (IsGarbageCollecting()) {
            FPlatformProcess::Sleep(0.05f);
        }

        UMyObject* myObj = NewObject<UMyObject>();

        FGraphEventRef task = FFunctionGraphTask::CreateAndDispatchWhenReady([&, OnCompleted]() {
            OnCompleted.ExecuteIfBound();
        }, TStatId(), NULL, ENamedThreads::GameThread);
    });
}
1 Like