日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何在UE4中创建线程

發(fā)布時(shí)間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何在UE4中创建线程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

FRunnable和FRunnableThread方法對于大多數(shù)問題來說無疑是一個(gè)可行的解決方案。 但是,在創(chuàng)建許多任務(wù)時(shí),您可能會(huì)達(dá)到CPU可以處理的并發(fā)上限,此時(shí)并發(fā)線程實(shí)際上會(huì)在爭用CPU時(shí)間時(shí)相互阻礙。 然后可能值得查看FQueuedThreadPool以限制任務(wù)可用的線程數(shù)。

虛幻引擎4還提供了全局GThreadPool ,但是此線程池僅設(shè)置為單個(gè)線程(UE4.14.3)。 它似乎只是為了在另一個(gè)核心上運(yùn)行并發(fā)任務(wù)。

下面的代碼是什么

  • 創(chuàng)建一個(gè)線程來計(jì)算前50,000個(gè)素?cái)?shù)
  • 將增量完成數(shù)據(jù)發(fā)送回游戲線程
  • 具有靜態(tài)訪問器,用于啟動(dòng),關(guān)閉和查找線程是否已完成。

靜態(tài)函數(shù)

您將在下面的代碼中注意到我使用靜態(tài)函數(shù)輕松啟動(dòng)新線程,如果我需要匆忙關(guān)閉線程(例如播放器退出),我也可以使用GameThread中的靜態(tài)Shutdown()函數(shù)游戲)

性能

我首先使用任務(wù)圖系統(tǒng)計(jì)算前50,000個(gè)素?cái)?shù),并創(chuàng)建50,000個(gè)任務(wù)(每個(gè)素?cái)?shù)找1個(gè))。

在本教程中看到的代碼中,我創(chuàng)建了一個(gè)專用線程來計(jì)算前50,000個(gè)素?cái)?shù)!

性能優(yōu)勢是非凡的!

我的fps在下面的代碼中為這個(gè)線程的整個(gè)運(yùn)行保持穩(wěn)定90(我選擇的最大fps)。

而對于任務(wù)圖系統(tǒng),當(dāng)我接近50,000時(shí),fps下降了最多40。

對于較大的任務(wù),請務(wù)必嘗試實(shí)際的多線程!

.H

//~~~~~ Multi Threading ~~~ class FPrimeNumberWorker : public FRunnable { /** Singleton instance, can access the thread any time via static accessor, if it is active! */static FPrimeNumberWorker* Runnable;/** Thread to run the worker FRunnable on */FRunnableThread* Thread;/** The Data Ptr */TArray<uint32>* PrimeNumbers;/** The PC */AVictoryGamePlayerController* ThePC;/** Stop this thread? Uses Thread Safe Counter */FThreadSafeCounter StopTaskCounter;//The actual finding of prime numbersint32 FindNextPrimeNumber();private:int32 PrimesFoundCount; public:int32 TotalPrimesToFind;//Done?bool IsFinished() const{return PrimesFoundCount >= TotalPrimesToFind;}//~~~ Thread Core Functions ~~~//Constructor / DestructorFPrimeNumberWorker(TArray<uint32>& TheArray, const int32 IN_PrimesToFindPerTick, AVictoryGamePlayerController* IN_PC);virtual ~FPrimeNumberWorker();// Begin FRunnable interface.virtual bool Init();virtual uint32 Run();virtual void Stop();// End FRunnable interface/** Makes sure this thread has stopped properly */void EnsureCompletion();//~~~ Starting and Stopping Thread ~~~/* Start the thread and the worker from static (easy access)! This code ensures only 1 Prime Number thread will be able to run at a time. This function returns a handle to the newly started instance.*/static FPrimeNumberWorker* JoyInit(TArray<uint32>& TheArray, const int32 IN_TotalPrimesToFind, AVictoryGamePlayerController* IN_PC);/** Shuts down the thread. Static so it can easily be called from outside the thread context */static void Shutdown();static bool IsThreadFinished();};

.CPP

//*********************************************************** //Thread Worker Starts as NULL, prior to being instanced // This line is essential! Compiler error without it FPrimeNumberWorker* FPrimeNumberWorker::Runnable = NULL; //***********************************************************FPrimeNumberWorker::FPrimeNumberWorker(TArray<uint32>& TheArray, const int32 IN_TotalPrimesToFind, AVictoryGamePlayerController* IN_PC): ThePC(IN_PC), TotalPrimesToFind(IN_TotalPrimesToFind), StopTaskCounter(0), PrimesFoundCount(0) {//Link to where data should be storedPrimeNumbers = &TheArray;Thread = FRunnableThread::Create(this, TEXT("FPrimeNumberWorker"), 0, TPri_BelowNormal); //windows default = 8mb for thread, could specify more }FPrimeNumberWorker::~FPrimeNumberWorker() {delete Thread;Thread = NULL; }//Init bool FPrimeNumberWorker::Init() {//Init the Data PrimeNumbers->Empty();PrimeNumbers->Add(2);PrimeNumbers->Add(3);if(ThePC) {ThePC->ClientMessage("**********************************");ThePC->ClientMessage("Prime Number Thread Started!");ThePC->ClientMessage("**********************************");}return true; }//Run uint32 FPrimeNumberWorker::Run() {//Initial wait before startingFPlatformProcess::Sleep(0.03);//While not told to stop this thread // and not yet finished finding Prime Numberswhile (StopTaskCounter.GetValue() == 0 && ! IsFinished()){PrimeNumbers->Add(FindNextPrimeNumber());PrimesFoundCount++;//***************************************//Show Incremental Results in Main Game Thread!// Please note you should not create, destroy, or modify UObjects here.// Do those sort of things after all thread are completed.// All calcs for making stuff can be done in the threads// But the actual making/modifying of the UObjects should be done in main game thread.ThePC->ClientMessage(FString::FromInt(PrimeNumbers->Last()));//***************************************//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//prevent thread from using too many resources//FPlatformProcess::Sleep(0.01);//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}//Run FPrimeNumberWorker::Shutdown() from the timer in Game Thread that is watching//to see when FPrimeNumberWorker::IsThreadFinished()return 0; }//stop void FPrimeNumberWorker::Stop() {StopTaskCounter.Increment(); }FPrimeNumberWorker* FPrimeNumberWorker::JoyInit(TArray<uint32>& TheArray, const int32 IN_TotalPrimesToFind, AVictoryGamePlayerController* IN_PC) {//Create new instance of thread if it does not exist// and the platform supports multi threading!if (!Runnable && FPlatformProcess::SupportsMultithreading()){Runnable = new FPrimeNumberWorker(TheArray,IN_TotalPrimesToFind,IN_PC); }return Runnable; }void FPrimeNumberWorker::EnsureCompletion() {Stop();Thread->WaitForCompletion(); }void FPrimeNumberWorker::Shutdown() {if (Runnable){Runnable->EnsureCompletion();delete Runnable;Runnable = NULL;} }bool FPrimeNumberWorker::IsThreadFinished() {if(Runnable) return Runnable->IsFinished();return true; } int32 FPrimeNumberWorker::FindNextPrimeNumber() {//Last known prime number + 1int32 TestPrime = PrimeNumbers->Last();bool NumIsPrime = false;while( ! NumIsPrime){NumIsPrime = true;//Try Next NumberTestPrime++;//Modulus from 2 to current number - 1 for(int32 b = 2; b < TestPrime; b++){//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//prevent thread from using too many resources//FPlatformProcess::Sleep(0.01);//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~if(TestPrime % b == 0) {NumIsPrime = false;break;//~~~}}}//Success!return TestPrime; }

Starting the thread

//In the .h for the player controller // this is the actual data TArray<uint32> PrimeNumbers;

?

//player controller .cpp //Multi-threading, returns handle that could be cached. // use static function FPrimeNumberWorker::Shutdown() if necessary FPrimeNumberWorker::JoyInit(PrimeNumbers, 50000, this);

線程管理

您應(yīng)該查看“FRunnable”的代碼庫,以查看多線程和鎖定/解鎖保護(hù)的擴(kuò)展用途。

我用了一個(gè)簡單的例子來幫助你入門,但是多線程時(shí)需要考慮很多:)

使用Sleep進(jìn)行線程管理

你應(yīng)該考慮使用

FPlatformProcess :: Sleep ( 秒 );

防止1個(gè)線程占用太多系統(tǒng)資源:)

什么不該做

  • 不要嘗試從其他線程修改,創(chuàng)建或刪除UObject!

您可以準(zhǔn)備所有數(shù)據(jù)/進(jìn)行所有計(jì)算,但只有游戲線程應(yīng)該實(shí)際產(chǎn)生/修改/刪除UObjects / AActors。

  • 不要嘗試在游戲線程之外使用TimerManager :)
  • 不要試圖繪制調(diào)試行/點(diǎn)等,因?yàn)樗赡軙?huì)崩潰,即DrawDebugLine(等...)
  • 通知(自4.11起):

    如果要使用計(jì)時(shí)器,刪除和修改變量,請使用它:

    #include “Async.h” ...AsyncTask ( ENamedThreads :: GameThread , []() {//這里在游戲線程上執(zhí)行的代碼});

    GameThread中的計(jì)時(shí)器功能

    您可以在游戲線程中運(yùn)行計(jì)時(shí)器功能,以定期檢查您創(chuàng)建的其他線程收集的數(shù)據(jù)。

    如何支持單線程平臺?

    如果您的代碼絕對必須在HTML5等單線程環(huán)境中運(yùn)行,那么請查看

    AsyncIOSystemBase.h

    struct CORE_API FAsyncIOSystemBase:public FIOSystem,FRunnable,FSingleThreadRunnable

    Runnable可以擴(kuò)展SingleThreadRunnable,并為單線程情況下的FRunnable鉤子返回自己:

/*** Gets single thread interface pointer used for ticking this runnable when multi-threading is disabled.* If the interface is not implemented, this runnable will not be ticked when FPlatformProcess::SupportsMultithreading() is false.** @return Pointer to the single thread interface or nullptr if not implemented.*/ virtual class FSingleThreadRunnable* GetSingleThreadInterface( ) {return nullptr; }

總結(jié)

以上是生活随笔為你收集整理的如何在UE4中创建线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。