Interruptable Latent Blueprint Nodes

I used an enum class ref and ExpandEnumAsExecs.

UENUM(BlueprintType)
enum class OUT_EXEC : uint8
{
    Completed,
    Interrupted
};

Your latent function could look like:

UFUNCTION(BlueprintCallable, Category="MyCategory", meta=(ExpandEnumAsExecs="exec", Latent, WorldContext="WorldContextObject", LatentInfo="LatentInfo", interupt="false"))
void Generate_async(UObject* WorldContextObject, UPARAM(ref) bool interrupt, AActor* Some_actor, OUT_EXEC& exec, struct FLatentActionInfo LatentInfo);

then you would pass interrupt and exec reference as well as Some_actor pointer down to your subclass of FPendingLatentAction. Your UpdateOperation(FLatentResponse& Response) implementation could look something like this:

virtual void UpdateOperation(FLatentResponse& Response) override
{
    // Do stuff with Some_actor. Maybe an iteration that takes a long time.
    Some_actor->DoWork(iter++);
	bool finish_flag = Some_actor->WorkIsCompleted();
	if (finish_flag)
	{
            exec = OUT_EXEC::Completed;
	}
    else if (interrupt) // don't run this if finish_flag is already true
    {
           Some_actor->CancelWork();
           exec = OUT_EXEC::Interrupted;
    }
	Response.FinishAndTriggerIf(finish_flag || interrupt, ExecutionFunction, OutputLink, CallbackTarget);
}

Now when you want to interrupt this, you just need to set the bool variable that you passed in as a reference to true. A down side of this is that you can only call latent nodes from an event graph so you either have a bunch of boolean variables in your blueprint or you can wrap all this up in a separate object that can be created and disposed of when it’s all done.

Here is an image to help me explain how it works.

That Generate Async node is a latent node that I created using what I explained above. This particular node will pass information off to a thread pool if the pool is not too full. If it is too full it sets my OUT_EXEC exec to Failed and triggers the response, otherwise it adds the work to the pool and when the work is completed sets the OUT_EXEC exec to Success and triggers the response. As a result, the appropriate output exec pin gets called.