【UE4 C++ 基礎知識】<14> 多線程——AsyncTask


概念

AsyncTask

  • AsyncTask 系統是一套基於線程池的異步任務處理系統。每創建一個AsyncTas,都會被加入到線程池中進行執行
  • AsyncTask 泛指 FAsyncTaskFAutoDeleteAsyncTask,一般聲明為友元函數,FNonAbandonableTask 派生類作為模板
  • FNonAbandonableTask 是要繼承的基類,不可被終止的任務,可以看作是任務執行體的抽象

FAsyncTask

  • 模板類
  • DoWork() 實現具體任務,自定義類作為模板參數
  • FAsyncTask 初始化后,默認添加到線程池FQueuedThreadPool。可以指定其他線程池
    • StartBackgroundTask() 將任務扔到線程池中去執行
    • StartSynchronousTask() 直接在當前線程執行
  • EnsureCompletion() 可以等待任務完成
  • 執行結束需要手動停止或刪除任務

FAutoDeleteAsyncTask

  • 與 FAsyncTask 類似
  • 執行結束自動刪除伍。執行完成后,會通過線程池的 Destroy 函數刪除,或者 DoWork 完成后刪除

FQueuedThreadPool線程池

  • FQueuedThreadPool: 虛基類,定義線程池常用的接口。FQueueThreadPoolBase 繼承FQueuedThreadPool,實現具體的方法。
  • FQueueThreadPoolBase 維護了多個線程FQueuedThread與多個任務隊列IQueuedWork
    • TArray<IQueuedWork*> QueuedWork(要被執行的任務)
    • TArray<FQueuedThread*> QueuedThreads(空閑的線程)
    • TArray<FQueuedThread*> AllThreads(所有的線程)。
  • 線程池里的線程都是FQueuedThread類型,FQueuedThread是繼承自FRunnable的線程執行體
  • FRunnableThread 表示線程本身,該類會派生出平台相關的子類

FEvent

  • FEvent: 虛基類,提供了事件操作的接口,用於線程的掛起/喚醒(Wait()/Trigger())

image

使用方式

簡單使用方式 Lambda

  • 可指定線程
  • 可根據指定線程用於多線程調用主線程里的東西
    AsyncTask(ENamedThreads::GameThread, [=]()
    {
        // Do Something
    });
    

手動銷毀方式:FNonAbandonableTask 與 FAsyncTask

  • SimpleAsyncTask 類

    class  SimpleAsyncTask :FNonAbandonableTask
    {
    	FString m_TaskName;
    	int32 m_MaxNumber;
    	friend class FAsyncTask<SimpleAsyncTask>;
    public:
    	// 構造函數
    	SimpleAsyncTask(const FString& TaskName, int32 MaxNumber)
    		: m_TaskName(TaskName), m_MaxNumber(MaxNumber) {}
    	// 析構函數
    	~SimpleAsyncTask() 
    	{
    		UE_LOG(LogTemp, Warning, TEXT("Task[%s] End"), *m_TaskName);
    	}
    
    	// 具體任務邏輯執行
    	void DoWork()
    	{
    		UE_LOG(LogTemp, Warning, TEXT("Task[%s] Start"), *m_TaskName);
    		int CurrentNum = 0;
    		while (CurrentNum < m_MaxNumber)
    		{
    			CurrentNum++;
    			UE_LOG(LogTemp, Warning, TEXT("Task[%s] CurrentNum:%d"), *m_TaskName, CurrentNum);
    		}
    	}
    
    	// 固定寫法,本類將作為函數參數
    	FORCEINLINE TStatId GetStatId() const
    	{
    		RETURN_QUICK_DECLARE_CYCLE_STAT(SimpleAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
    	}
    };
    
  • 調用任務的Actor——AAsyncTaskActor

    UFUNCTION(BlueprintCallable)
    	void CreateAsyncTask(const FString& TaskName, int32 MaxNumber);
    
    void AAsyncTaskActor::CreateAsyncTask(const FString& TaskName, int32 MaxNumber)
    {
    	UE_LOG(LogTemp, Warning, TEXT("Task[%s] Created"), *TaskName);
    	FAsyncTask<SimpleAsyncTask>* MyTask = new FAsyncTask<SimpleAsyncTask>(TaskName, MaxNumber);
    	MyTask->StartBackgroundTask();
    	
    	// MyTask->StartSynchronousTask; 在當前線程執行,可能會導致主線程阻塞
    	// MyTask->IsDone()  可以配合定時器檢測是否完成任務
    
    	//等待任務完成后,進行手動刪除
    	MyTask->EnsureCompletion();
    	delete MyTask;
    	MyTask = nullptr;	
    }
    

自動銷毀方式:FNonAbandonableTask 與 FAutoDeleteAsyncTask

  • AutoDeleteSimpleAsyncTask 類

    class  AutoDeleteSimpleAsyncTask :FNonAbandonableTask
    {
    	FString m_TaskName;
    	int32 m_MaxNumber;
    	friend class FAutoDeleteAsyncTask<AutoDeleteSimpleAsyncTask>;
    public:
    	// 構造函數
    	AutoDeleteSimpleAsyncTask(const FString& TaskName, int32 MaxNumber)
    		: m_TaskName(TaskName), m_MaxNumber(MaxNumber) {}
    	// 析構函數
    	~AutoDeleteSimpleAsyncTask()
    	{
    		UE_LOG(LogTemp, Warning, TEXT("Task[%s] End"), *m_TaskName);
    	}
    
    	// 具體任務邏輯執行
    	void DoWork()
    	{
    		UE_LOG(LogTemp, Warning, TEXT("Task[%s] Start"), *m_TaskName);
    		int CurrentNum = 0;
    		while (CurrentNum < m_MaxNumber)
    		{
    			CurrentNum++;
    			UE_LOG(LogTemp, Warning, TEXT("AutoDeleteTask[%s] CurrentNum:%d"), *m_TaskName, CurrentNum);
    		}
    	}
    
    	// 固定寫法,本類將作為函數參數
    	FORCEINLINE TStatId GetStatId() const
    	{
    		RETURN_QUICK_DECLARE_CYCLE_STAT(SimpleAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
    	}
    };
    
  • 調用任務的Actor——AAsyncTaskActor

    UFUNCTION(BlueprintCallable)
    	void CreateAutoDeleteAsyncTask(const FString& TaskName, int32 MaxNumber);
    
    void AAsyncTaskActor::CreateAutoDeleteAsyncTask(const FString& TaskName, int32 MaxNumber)
    {
    	UE_LOG(LogTemp, Warning, TEXT("AutoDeleteTask[%s] Created"), *TaskName);
    	// 任務完成后,自動刪除
    	(new FAutoDeleteAsyncTask<AutoDeleteSimpleAsyncTask>(TaskName, MaxNumber))->StartSynchronousTask();
    }
    

image

參考


免責聲明!

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



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