UE4的多線程


1. 源代碼

  AsyncWork.h

2. 多線程的使用

  參考文檔:https://wiki.unrealengine.com/Using_AsyncTasks

  當我們需要執行一個需要很長時間的任務時,放在主線程里會導致很卡,把此任務放到其他線程里則會好很多,此時多線程就可以起到關鍵的作用了。

  在UE4里,我們可以使用FAsyncTask 或者FAutoDeleteAsyncTask。

  使用FAsyncTask 時,我們需要手動停止或刪除任務;使用FAutoDeleteAsyncTask時,系統則會自動在任務結束后,刪除任務。

  需要先建個繼承FNonAbandonableTask的類,如源碼中的例子:

class ExampleAutoDeleteAsyncTask : public FNonAbandonableTask
    {
        friend class FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>;

        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<ExampleAutoDeleteAsyncTask>(5)->StartBackgroundTask();

        // do an example job now, on this thread
        (new FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>(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<ExampleAutoDeleteAsyncTask>;

    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<ExampleAutoDeleteAsyncTask>(10, GetWorld(), this);
    if (task) task->StartBackgroundTask();
    //此任務會在當前線程中馬上開始。
    auto task2= new FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>(15, GetWorld(), this);
    if (task2) task2->StartSynchronousTask();
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM