如何在UE4中创建线程

FRunnableFRunnableThread方法对于大多数问题来说无疑是一个可行的解决方案。 但是,在创建许多任务时,您可能会达到CPU可以处理的并发上限,此时并发线程实际上会在争用CPU时间时相互阻碍。 然后可能值得查看FQueuedThreadPool以限制任务可用的线程数。

虚幻引擎4还提供了全局GThreadPool ,但是此线程池仅设置为单个线程(UE4.14.3)。 它似乎只是为了在另一个核心上运行并发任务。

下面的代码是什么

  • 创建一个线程来计算前50,000个素数
  • 将增量完成数据发送回游戏线程
  • 具有静态访问器,用于启动,关闭和查找线程是否已完成。

静态函数

您将在下面的代码中注意到我使用静态函数轻松启动新线程,如果我需要匆忙关闭线程(例如播放器退出),我也可以使用GameThread中的静态Shutdown()函数游戏)

性能

我首先使用任务图系统计算前50,000个素数,并创建50,000个任务(每个素数找1个)。

在本教程中看到的代码中,我创建了一个专用线程来计算前50,000个素数!

性能优势是非凡的!

我的fps在下面的代码中为这个线程的整个运行保持稳定90(我选择的最大fps)。

而对于任务图系统,当我接近50,000时,fps下降了最多40。

对于较大的任务,请务必尝试实际的多线程!

.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);

线程管理

您应该查看“FRunnable”的代码库,以查看多线程和锁定/解锁保护的扩展用途。

我用了一个简单的例子来帮助你入门,但是多线程时需要考虑很多:)

使用Sleep进行线程管理

你应该考虑使用

  FPlatformProcess :: Sleep ( 秒 );

防止1个线程占用太多系统资源:)

什么不该做

  • 不要尝试从其他线程修改,创建或删除UObject!

您可以准备所有数据/进行所有计算,但只有游戏线程应该实际产生/修改/删除UObjects / AActors。

  • 不要尝试在游戏线程之外使用TimerManager :)
  • 不要试图绘制调试行/点等,因为它可能会崩溃,即DrawDebugLine(等...)
  • 通知(自4.11起):

    如果要使用计时器,删除和修改变量,请使用它:

      #include “Async.h” ...AsyncTask ( ENamedThreads :: GameThread , []() {//这里在游戏线程上执行的代码});
    

    GameThread中的计时器功能

    您可以在游戏线程中运行计时器功能,以定期检查您创建的其他线程收集的数据。

    如何支持单线程平台?

    如果您的代码绝对必须在HTML5等单线程环境中运行,那么请查看

    AsyncIOSystemBase.h

      struct CORE_API FAsyncIOSystemBase:public FIOSystem,FRunnable,FSingleThreadRunnable
    

    Runnable可以扩展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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Leveldb源码剖析疑问]-block_builder.cc之Add函数

Add函数是给一个Data block中添加对应的key和value,函数源码如下,其中有一处不理解: L30~L34是更新last_key_的,不理解这里干嘛不直接last_key_ key.ToString(); 写成 // Update state last_key_.resize(shared); last_key_.append(key.data() shared, non_shared); assert(S…

UE4多线程任务系统详解

首先&#xff0c;了解一下该系统重要的数据类型. 1. FQueuedThreadPool&#xff1a;虚基类&#xff0c;队列线程池, FQueuedThreadPoolBase继承自FQueuedThreadPool&#xff0c; FQueuedThreadPoolBase维护了一个TArray<IQueuedWork*> QueuedWork(需要被执行的工作)…

UE4异步编程专题 - 线程池FQueuedThreadPool

1. FQueuedThreadPool & IQueuedWork FQueuedThreadPool是UE4中抽象出的线程池。线程池由若干个Worker线程&#xff0c;和一个同步队列构成。UE4把同步队列执行的任务抽象为IQueuedWork. 线程池的同步队列&#xff0c;就是一个IQueuedWork的队列了。借用wiki上线程池的图,…

UE4异步编程专题 - 多线程

专题的第二篇&#xff0c;我们聊聊UE4中的多线程的基础设施。UE4中最基础的模型就是FRunnable和FRunnableThread&#xff0c;FRunnable抽象出一个可以执行在线程上的对象&#xff0c;而FRunnableThread是平台无关的线程对象的抽象。后面的篇幅会详细讨论这些基础设施。 1. FRu…

坑爹的UICollectionView

最近用UICoolectionView的时候遇到一个很DT的问题&#xff0c;我往VC里加12个视图&#xff0c;结果显示成这样&#xff08;右边是期待的样子&#xff09;&#xff1a; 研究了一下午&#xff0c;终于发现了问题&#xff1a; interface FpLabelCell : UICollectionViewCellproper…

UE4异步编程专题 - TFunction

0. 关于这个专题 游戏要给用户良好的体验&#xff0c;都会尽可能的保证60帧或者更高的fps。一帧留给引擎的时间也不过16ms的时长&#xff0c;再除去渲染时间&#xff0c;留给引擎时间连10ms都不到&#xff0c;能做的事情是极其有限的。同步模式执行耗时的任务&#xff0c;时长…

Python用subprocess的Popen来调用系统命令

当我们须要调用系统的命令的时候&#xff0c;最先考虑的os模块。用os.system()和os.popen()来进行操作。可是这两个命令过于简单&#xff0c;不能完毕一些复杂的操作&#xff0c;如给执行的命令提供输入或者读取命令的输出&#xff0c;推断该命令的执行状态&#xff0c;管理多个…

7700装win7

1.可能不能安装版本太新的win7系统,会蓝屏 2.第一次重启后,系统会提示硬件太新,系统不支持,不用理会.可以用shiftF10,进入windows/system32/oobe目录,执行msoobe手动安装. 3.第一次进入系统后,尽早关闭系统更新,除了在控制面板中关闭,还要在services.msc中关闭windows update服…

UE4高级功能--初探超大无缝地图的实现LevelStream

LevelStream 实现超大无缝地图--官方文档学习 The Level Streaming feature makes it possible to load and unload map files into memory as well as toggle their visibility all during play. This makes it possible to have worlds broken up into smaller chunks so th…

Noip 2014酱油记+简要题解

好吧&#xff0c;day2T1把d默认为1也是醉了&#xff0c;现在只能期待数据弱然后怒卡一等线吧QAQDay0 第一次下午出发啊真是不错&#xff0c;才2小时左右就到了233&#xff0c;在车上把sao和fate补掉就到了 然后到宾馆之后&#xff0c;没wifi的生活就是惨啊QAQ 把空境补完就睡了…

一个取消事件的简单js例子(事件冒泡与取消默认行为)

先上代码&#xff1a; <div idouter onclickalert("我是outer")><div id"middle" onclickalert("我是middle")><div id"inner" onclickmyBubble(arguments[0]);alert("我是inner")><a onclickmyDefaul…

inside uboot (二) 启动流程

1. S3C6410 启动流程 1). 6410上电后&#xff0c;首先执行片内iROM的程序&#xff08;BL0&#xff09;&#xff0c;初始化时钟和看门狗等外围器件。 2). 然后把flash中头4K&#xff08;BL1&#xff09;的内容加载到片内的SRAM中执行。 3). 在SRAM中执行的BL1&#xff0c;初始…

你理解我的意思么?

在最近一次的电话会议里, 某leader前后说了十来句, "你理解我的意思么?". 说实话, 有些我都没理解, 不过我听到的大家的答复都是"理解!", "明白!". Leader问这样的问题, 期望是得到对方给你反馈, 结果大部分人不会直接对上级说, "是的,我不…

inside uboot (三) 异常向量表

1. 异常向量表概述 从上面的地址映射来看&#xff0c;中断向量表的地址为0xD0037400&#xff0c;因此如果我们想在SRAM中&#xff0c;也就是BL1中处理异常的话&#xff0c; 就需要把我们的异常向量表拷贝到这个地址上。或者我们可以在链接脚本中直接指定代码的地址。 如果在主…

unity3d教程游戏包含的一切文件导入资源

http://www.58player.com/blog-2327-954.html 导入资源 将文件增加至工程文件夹的资源 (Assets) 文件夹后&#xff0c;Unity 将自动检测文件。将任何资源 (Assets) 放入资源文件夹后&#xff0c;资源 (Assets) 将显现在工程视图 (Project View) 中。 此工程视图 (Project Vie…

javascript 事件知识集锦

1.事件委托极其应用 转载的链接&#xff1a; http://www.webhek.com/event-delegate/#comments 2. 解析javascript事件机制 转载链接&#xff1a; http://www.nowamagic.net/javascript/js_EventAnalysis.php转载于:https://www.cnblogs.com/alicePanZ/p/4097017.html

ubuntu软件(查看文件差异)

你可以在ubuntu系统自带的软件---》ubuntu软件中心输入&#xff1a;meld diff 就可以安装。转载于:https://www.cnblogs.com/kobigood/p/4097411.html

关闭日志

/** Used by tools which include only core to disable log file creation. */ #ifndef ALLOW_LOG_FILE#define ALLOW_LOG_FILE 0 #endif 修改引擎源码的ALLOW_LOG_FILE为0

【Linux/Ubuntu学习6】unbuntu 下载android源码

在Windows下安装Cygwin&#xff0c;通过Cygwin也可在Windows里通过本文的下载步骤下载Android源码。以下为在Ubuntu下下载Google Android4.4源码的步骤&#xff1a; 1. 安装curl 与 git sudo apt-get install curl sudo apt-get install git-core 2 安装 Repo a) 建立Repo的安装…