1. 源代码
AsyncWork.h
2. 多线程的使用
参考文档:https://wiki.unrealengine.com/Using_AsyncTasks
当我们需要执行一个需要很长时间的任务时,放在主线程里会导致很卡,把此任务放到其他线程里则会好很多,此时多线程就可以起到关键的作用了。
在UE4里,我们可以使用FAsyncTask 或者FAutoDeleteAsyncTask。
使用FAsyncTask 时,我们需要手动停止或删除任务;使用FAutoDeleteAsyncTask时,系统则会自动在任务结束后,删除任务。
需要先建个继承FNonAbandonableTask的类,如源码中的例子:
class ExampleAutoDeleteAsyncTask : public FNonAbandonableTask { friend class FAutoDeleteAsyncTask; int32 ExampleData; ExampleAutoDeleteAsyncTask(int32 InExampleData) : ExampleData(InExampleData) { } void DoWork() { ... do the work here } FORCEINLINE TStatId GetStatId() const { RETURN_QUICK_DECLARE_CYCLE_STAT(ExampleAutoDeleteAsyncTask, STATGROUP_ThreadPoolAsyncTasks); } };
然后具体调用就是:
void Example() { // start an example job (new FAutoDeleteAsyncTask(5)->StartBackgroundTask(); // do an example job now, on this thread (new FAutoDeleteAsyncTask (5)->StartSynchronousTask(); }
注意:StartBackgroundTask()是在另一个线程中执行此任务;StartSynchronousTask()是在当前线程中马上执行此任务。
举个例子:
.h: #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Kismet/KismetSystemLibrary.h" #include "MyActor.generated.h" UCLASS() class ASYNCWORKSTUDY_API AMyActor : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AMyActor(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; void TestAsync(FString Content); //多线程例子 void Example(); }; class ExampleAutoDeleteAsyncTask : public FNonAbandonableTask { friend class FAutoDeleteAsyncTask; int32 ExampleData; UObject* Object; AMyActor* Target; ExampleAutoDeleteAsyncTask(int32 InExampleData, UObject* InObject, AMyActor* InTarget) : ExampleData(InExampleData), Object(InObject), Target(InTarget) { } void DoWork() { UKismetSystemLibrary::PrintString(Object, FString::FromInt(ExampleData)); //调用AMyactor的测试函数 if (Target) Target->TestAsync("Success"); } FORCEINLINE TStatId GetStatId() const { RETURN_QUICK_DECLARE_CYCLE_STAT(ExampleAutoDeleteAsyncTask, STATGROUP_ThreadPoolAsyncTasks); } }; .cpp: #include "MyActor.h" // Sets default values AMyActor::AMyActor() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; } // Called when the game starts or when spawned void AMyActor::BeginPlay() { Super::BeginPlay(); UKismetSystemLibrary::PrintString(this, "Hello"); Example(); } // Called every frame void AMyActor::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void AMyActor::TestAsync(FString Content) { UKismetSystemLibrary::PrintString(this, Content); } void AMyActor::Example() { //在其他线程里执行此任务 auto task = new FAutoDeleteAsyncTask (10, GetWorld(), this); if (task) task->StartBackgroundTask(); //此任务会在当前线程中马上开始。 auto task2= new FAutoDeleteAsyncTask (15, GetWorld(), this); if (task2) task2->StartSynchronousTask(); }