概念
AsyncTask
- AsyncTask 系統是一套基於線程池的異步任務處理系統。每創建一個AsyncTas,都會被加入到線程池中進行執行
- AsyncTask 泛指
FAsyncTask
和FAutoDeleteAsyncTask
,一般聲明為友元函數,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())
使用方式
簡單使用方式 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(); }
參考
- FAsyncTask
- FAutoDeleteAsyncTask
- FNonAbandonableTask
- Legacy/Using AsyncTasks
- 《Exploring in UE4》多線程機制詳解[原理分析]
- \EpicGames\UE_4.26\Engine\Source\Runtime\Core\Public\Async\AsyncWork.h