UE4中使用多线程的有两种方式,一种方式就是使用FRunnable和FRunnableThread,另一种方式是Task Graph System。Task Graph System有时会占用游戏线程的时间,适合用在简单的计算或者需要开多个线程的情况。FRunnable适用于复杂运算。但是当创建太多线程后,有可能达到CPU的上限,这些线程就会为了抢占CPU的时间而彼此阻碍。UE4提供了FQueuedThreadPool来限制最大的线程数量。

  这种方式需要定义一个类继承自FRunnable,并且实现Init,Run,Stop,Exit。还需要一个FRunnableThread对象来创建和销毁线程。

  具体代码:

#pragma once

#include "CoreMinimal.h"
#include "Runnable.h"
#include "RunnableThread.h" class TESTTARRAY_API AudioRecordThread : public FRunnable
{
public:
AudioRecordThread(FString threadName);
~AudioRecordThread(); //暂停线程
void PauseThread();
//继续线程
void ContinueThread();
//停止线程
void StopThread(); bool IsThreadPaused();
bool IsThreadKilled(); private:
FRunnableThread* Thread;
FThreadSafeCounter StopTaskCounter;
FCriticalSection m_mutex;
public:
//override Frunnable Function
virtual bool Init() override;
virtual uint32 Run() override;
virtual void Stop() override;
virtual void Exit() override; private:
FThreadSafeBool m_Kill;
FThreadSafeBool m_Pause;
};
#include "AudioRecordThread.h"
#include "Engine.h" AudioRecordThread::AudioRecordThread(FString threadName) : StopTaskCounter()
{
m_Kill = false;
m_Pause = false;
Thread = FRunnableThread::Create(this, *threadName, , TPri_BelowNormal);
} AudioRecordThread::~AudioRecordThread()
{
if (Thread)
{
delete Thread;
Thread = nullptr;
}
} void AudioRecordThread::PauseThread()
{
m_Pause = true;
} void AudioRecordThread::ContinueThread()
{
m_Pause = false;
} void AudioRecordThread::StopThread()
{
Stop();
if (Thread)
{
Thread->WaitForCompletion();
}
}
//需要注意的是在其他线程不能对UObject进行操作,不能使用TimerManager,不能使用DrawDebugLine。 bool AudioRecordThread::IsThreadPaused()
{
return (bool)m_Pause;
} bool AudioRecordThread::IsThreadKilled()
{
return (bool)m_Kill;
} bool AudioRecordThread::Init()
{
GEngine->AddOnScreenDebugMessage(-, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadInit"));
return true;
} uint32 AudioRecordThread::Run()
{
//使用该函数Sleep
FPlatformProcess::Sleep(0.03);
while (StopTaskCounter.GetValue() == && !m_Kill)
{
if (m_Pause)
{
GEngine->AddOnScreenDebugMessage(-, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadPause"));
if (m_Kill)
{
return ;
}
}
else
{
GEngine->AddOnScreenDebugMessage(-, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadLoop")); m_mutex.Lock();
//需要同步处理的内容 m_mutex.Unlock(); FPlatformProcess::Sleep(0.01);
}
}
return ;
} void AudioRecordThread::Stop()
{
StopTaskCounter.Increment();
m_Kill = true;
m_Pause = false;
GEngine->AddOnScreenDebugMessage(-, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadStop"));
} void AudioRecordThread::Exit()
{
GEngine->AddOnScreenDebugMessage(-, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadExit"));
}

  创建线程:

m_AudioRecordThread = new AudioRecordThread("AudioRecordThread1");

,  构造函数中会用FRunnableThread::Create来创建线程。

  停止线程:

    if (m_AudioRecordThread)
{
m_AudioRecordThread->StopThread();
delete m_AudioRecordThread;
m_AudioRecordThread = nullptr;
}

  在StopThread中会调用Stop来控制相关状态量完成线程循环,Thread->WaitForCompletion(),会使调用StopThread的线程即主线程悬挂,当线程循环完成后继续,继续后删除m_AudioRecordThread对象。需要注意的是这样停止线程会调用两次Stop函数,所以Stop中最好只执行控制线程循环停止的状态量。

  使用FPlatformProcess::Sleep(0.03)来等待,避免线程占用过多的资源。

  线程锁:

    使用m_mutex.Lock();和m_mutex.Unlock();包裹住需要同步的代码即可。

  需要注意的是在其他线程不能对UObject进行操作,不能使用TimerManager,不能使用DrawDebugLine。要在游戏线程执行代码可以这样用:

#include "Async.h"
...
AsyncTask(ENamedThreads::GameThread, []() {
// code to execute on game thread here
});

  另外我这里使用多线程是做录音相关功能,用到了AudioClient.h这个头文件,因为这个文件用到了windows的东西,所以用在UE4里会报错,所以需要把这个头文件放到CPP里包含,用到的struct使用前置声明。

  

UE4 多线程(一)的更多相关文章

  1. [UE4]多线程开关,开启的解决方案

    像这样直接获取值就会被警告. 解决方法:定义一个变量speed,然后在“Blueprint Update Animation”事件中赋值给这个变量. 这样就不会被警告了. 另外一种解决方法:就是关掉多 ...

  2. 《Exploring in UE4》多线程机制详解[原理分析]

    转自:https://zhuanlan.zhihu.com/c_164452593 目录一.概述二."标准"多线程三.AsyncTask系统3.1 FQueuedThreadPoo ...

  3. UE4 Sockets多线程TCP通信

    转自:https://blog.csdn.net/zilisen/article/details/75007447 一.简介 UE4引擎是提供了Sockets模块和Networking模块的,博主在研 ...

  4. UE4 Socket多线程非阻塞通信

    转自:https://blog.csdn.net/lunweiwangxi3/article/details/50468593 ue4自带的Fsocket用起来依旧不是那么的顺手,感觉超出了我的理解范 ...

  5. UE4的多线程

    1. 源代码 AsyncWork.h 2. 多线程的使用 参考文档:https://wiki.unrealengine.com/Using_AsyncTasks 当我们需要执行一个需要很长时间的任务时 ...

  6. 【UE4 C++ 基础知识】<12> 多线程——FRunnable

    概述 UE4里,提供的多线程的方法: 继承 FRunnable 接口创建单个线程 创建 AsyncTask 调用线程池里面空闲的线程 通过 TaskGraph 系统来异步完成一些自定义任务 支持原生的 ...

  7. 【UE4 C++ 基础知识】<13> 多线程——TaskGraph

    概述 TaskGraph 系统是UE4一套抽象的异步任务处理系统 TaskGraph 可以看作一种"基于任务的并行编程"设计思想下的实现 通过TaskGraph ,可以创建任意多线 ...

  8. 【UE4 C++ 基础知识】<14> 多线程——AsyncTask

    概念 AsyncTask AsyncTask 系统是一套基于线程池的异步任务处理系统.每创建一个AsyncTas,都会被加入到线程池中进行执行 AsyncTask 泛指 FAsyncTask 和 FA ...

  9. 《图解UE4渲染体系》Part 1 多线程渲染

    上回书<Part 0 引擎基础>说到,我们粗略地知道UE4是以哪些类来管理一个游戏场景里的数据的,但这仅仅是我们开始探索UE4渲染体系的一小步. 本回主要介绍UE4渲染体系中比较宏观顶层的 ...

随机推荐

  1. Apache Avro# 1.8.2 Specification (Avro 1.8.2规范)一

    h4 { text-indent: 0.71cm; margin-top: 0.49cm; margin-bottom: 0.51cm; direction: ltr; color: #000000; ...

  2. VMware_ubuntu设置共享文件夹

    1. 点击安装VMware tools 2.将/media/vmtool的压缩包复制到/home/pc/vm_tool下,应为原路径在root权限下竟然也是只读的,并且无法更改. 3.进入/home/ ...

  3. 如何将外部的obj模型导入OpenGL

    1.关于obj的说明. obj中存放的是顶点坐标信息(v),面的信息(f),法线(vn),纹理坐标(vt),以及材质(这个放在mtl)中 我使用CINEMA 4D导出用VS查看后的信息: CINEMA ...

  4. 转:JAVA常见错误处理方法 和 JVM内存结构

    OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏:二是调整JVM启动参数增大内存.OutOfMemor ...

  5. 【官方文档】Nginx模块Nginx-Rtmp-Module学习笔记(三)流式播放Live HLS视频

    源码地址:https://github.com/Tinywan/PHP_Experience HTTP Live Streaming(HLS)是由Apple Inc.实施的非常强大的流视频协议.HLS ...

  6. Kotlin——最详细的操作符与操作符重载详解(上)

    本篇文章为大家详细的介绍Koltin特有的操作符重载.或许对于有编程经验的朋友来说,操作符这个词绝对不陌生,就算没有任何编辑基础的朋友,数学中的算数运算符也绝不陌生.例如(+.-.*./.>.& ...

  7. Nginx 限制连接的实践 (DDOS)

    参考:  运维人员的日常 关于限制用户连接,Nginx 提供的模块: ngx_http_limit_req_module , ngx_http_limit_conn_module  , 还有 stre ...

  8. 【转】彻底理解js中this的指向,不必硬背。

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  9. 在阿里云 ECS 搭建 nginx https nodejs 环境(三、nodejs)

    在阿里云 ECS 搭建 nginx https nodejs 环境(三.nodejs) 在阿里云 ECS 搭建 nginx https nodejs 环境(三.nodejs) 第一步 指定版本源 执行 ...

  10. Java学习笔记23(Calendar类)

    Calendar意味日历,对Date类中的很多方法做了改进 Calendar类是一个抽象类,不可以见对象,需要子类完成实现 不过这个类有特殊之处,不需要创建子类对象,而是使用它的静态方法直接获取: 示 ...