UEC++ 多執行緒(一) FRunnable
虛幻官方文檔://docs.unrealengine.com/5.0/en-US/API/Runtime/Core/HAL/FRunnable/
FRunnable
- 「runnable」對象的介面。
- 可運行對象是在任意執行緒上「運行」的對象。調用使用模式是Init()、Run()、Exit()。將要「run」這個對象的執行緒總是使用那些調用語義。它在創建的執行緒上執行此操作,以便在這些調用的上下文中可以使用任何特定於執行緒的使用(TLS等)。「runnable」在Init()中完成所有的初始化。
- 如果初始化失敗,執行緒將停止執行並返回錯誤程式碼。如果成功,則在執行真正的執行緒工作的地方調用Run()。完成後,調用Exit()以允許正確的清理。
函數
- void Exit() 退出可運行對象
- bool Init() 初始化可運行對象。
- uint32 Run() 運行可運行對象。
- void Stop() 停止可運行對象。如果請求執行緒提前終止,則調用此函數。
- FSingleThreadRunnable GetSingleThreadInterface() 獲取在禁用多執行緒時用於勾選此可運行項的單執行緒介面指針。
程式碼流程示意:
自定義基於Runnable的類
// 頭文件 #pragma once #include "HAL/Runnable.h" #include "CoreMinimal.h" /** * */ class MX_API FTestRunnable:public FRunnable { public: FTestRunnable(FString ThreadName,class AActor1* a1) :MyThreadName(ThreadName), A1(a1) {}; virtual bool Init() override; virtual uint32 Run() override; virtual void Exit() override; FString MyThreadName; class AActor1* A1; protected: int32 RunCount = 0; static FCriticalSection CriticalSection; }; // 源文件 FCriticalSection FTestRunnable::CriticalSection; bool FTestRunnable::Init() { UE_LOG(LogTemp, Log, TEXT("%s 初始化!"), *MyThreadName); //GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Red, TEXT("%s 初始化!"), *MyThreadName); return IsValid(A1); } uint32 FTestRunnable::Run() { while (IsValid(A1)) { // 同步鎖 如果沒有這行程式碼 最終各個執行緒運行的總次數將會大於需要的次數 FScopeLock Lock(&CriticalSection); if (A1->TestCount < A1->TestTarget) { A1->TestCount++; RunCount++; // 節約資源 每100次列印一次 if (RunCount % 100 == 0) UE_LOG(LogTemp, Log, TEXT("%s %d"), *MyThreadName, RunCount); } else{break;} } return 0; } void FTestRunnable::Exit() { UE_LOG(LogTemp, Log, TEXT("%s 結束運行!執行次數:%d"), *MyThreadName, RunCount); }
執行執行緒的類:
// 頭文件 // 定義兩個變數用於計數 int32 TestCount; UPROPERTY(EditAnywhere) int32 TestTarget; // 源文件 用於創建和開啟執行緒 這裡我放在了BeginPlay中方便測試 FTestRunnable* Runnable1 = new FTestRunnable(TEXT("執行緒1"), this); FTestRunnable* Runnable2 = new FTestRunnable(TEXT("執行緒2"), this); FTestRunnable* Runnable3 = new FTestRunnable(TEXT("執行緒3"), this); FRunnableThread* RunnableThread1 = FRunnableThread::Create(Runnable1, *Runnable1->MyThreadName); FRunnableThread* RunnableThread2 = FRunnableThread::Create(Runnable2, *Runnable2->MyThreadName); FRunnableThread* RunnableThread3 = FRunnableThread::Create(Runnable3, *Runnable3->MyThreadName);
測試結果:這裡我設置的執行緒運行次數為:1000000