UE4 C++使用Multi Theard的教程

来源:互联网 发布:2016网络彩票开售 编辑:程序博客网 时间:2024/05/21 17:13
==前言==
之前尝试在Tick中遍历整个ULevel中的Actor,并取每个Actor的Type name的时候,发现获取到20+个的时候,UE4就会崩溃【也许是遍历到自己然后访问到自己了.....总之不明情况
于是尝试多次无果的情况下,准备直接上多线程
然后查doc
发现官方doc上对多线程的描述比较少,能查到的wiki只有两篇:
https://wiki.unrealengine.com/Multi-Threading:_How_to_Create_Threads_in_UE4
https://wiki.unrealengine.com/Multi-Threading:_Task_Graph_System
感觉写的不是太明白,于是开始自己研究【这是个错误的决定_(:з」∠)_
......
于是就有下面这篇教程了


==正文==
我的目标是写一个很简单的factory
主要的功能有create、remove、run、stop、exit
create时传入要使用多线程的类的指针、要在多线程中被执行的函数和线程的名字
remove、run、stop、exit都使用线程名来操作


首先说一下UE4中常用的多线程类:
FRunnableThread和FRunnable
https://docs.unrealengine.com/latest/INT/API/Runtime/Core/HAL/FRunnableThread/index.html
https://docs.unrealengine.com/latest/INT/API/Runtime/Core/HAL/FRunnable/index.html
使用FRunnableThread类的Create成员函数来创建一个新线程
创建需要传入一个FRunnable对象
可以通过override掉FRunnable类的Run、Exit等成员函数,来达到自定义功能
创建完毕后,可以通过调用FRunnable类的Run等成员函数让其在新的线程中运行
【其实就是调用个Run然后Run就在新的线程中运行了


具体的设计思路:
创建一个MultiThread类,为factory
在MultiThread类中创建一个内部类:ThreadClass,ThreadClass继承FRunnable,override了Run成员函数,ThreadClass同时存放着FRunnableThread Create返回的FRunnableThread对象的指针、要使用多线程的对象的指针和要在新线程中运行的函数的指针
MultiThread中还含有一个Map用于储存创建出来的所有的ThreadClass对象
在MultiThread中定义一系列的操作的函数


代码:
==========MultiThread.h==========

#pragma once


class [ProjectName]_API MultiThread {
public:
// 构造函数

MultiThread() = default;


// 析构函数
~MultiThread() = default;


public:
// 创建一个新线程
template <typename T>
static void create(T *objectPointer, void(T::*functionPointer)(void), FString threadName) {
// 创建新线程实例
ThreadClass tempThreadObject(objectPointer, functionPointer, threadName);
// 存入线程列表
MultiThread::threadList.Add(threadName, tempThreadObject);
}


// 删一个线程
static void remove(FString threadName);


// 运行一个线程
static void run(FString threadName);


// 停止一个线程
static void stop(FString threadName);


// 退出一个线程
static void exit(FString threadName);


private:
// Thread class
class ThreadClass : public FRunnable {
public:
// 构造函数
template <typename T>
ThreadClass(T *objectPointer, void(T::*functionPointer)(void), FString threadName) {
// 存入要运行多线程的对象的指针
this->objectPointer = (UObject *)objectPointer;
// 存入要使用多线程的函数的指针
this->functionPointer = (void(UObject::*)(void))functionPointer;
// 创建一个新FRunnableThread对象
this->runnableThread = FRunnableThread::Create(this, *threadName, 0, TPri_BelowNormal, 0);
}


// 析构函数
~ThreadClass();


public:
// 运行
virtual uint32 Run() override;


private:
// 对象的指针
UObject *objectPointer = nullptr;


// 函数的指针
void(UObject::*functionPointer)(void) = nullptr;


// FRunnableThread对象的指针
FRunnableThread *runnableThread = nullptr;
};


private:
// 线程列表
static TMap<FString, ThreadClass> threadList;
};

==========MultiThread.cpp==========
#include "MultiThread.h"


// 线程列表
TMap<FString, MultiThread::ThreadClass> MultiThread::threadList;


// 运行线程
void MultiThread::run(FString threadName) {
MultiThread::ThreadClass *tempThread = MultiThread::threadList.Find(threadName);
if (tempThread) {
tempThread->Run();
}
}


// 删除线程
void MultiThread::remove(FString threadName) {
MultiThread::ThreadClass *tempThread = MultiThread::threadList.Find(threadName);
if (tempThread) {
delete tempThread;
MultiThread::threadList.Remove(threadName);
}
}


// 停止
void MultiThread::stop(FString threadName) {
MultiThread::ThreadClass *tempThread = MultiThread::threadList.Find(threadName);
if (tempThread) {
tempThread->Stop();
}
}


// 退出
void MultiThread::exit(FString threadName) {
MultiThread::ThreadClass *tempThread = MultiThread::threadList.Find(threadName);
if (tempThread) {
tempThread->Exit();
}
}


// 析构函数
MultiThread::ThreadClass::~ThreadClass() {
this->objectPointer = nullptr;
this->functionPointer = nullptr;
delete this->runnableThread;
this->runnableThread = nullptr;
}


// 运行
uint32 MultiThread::ThreadClass::Run() {
// 这个是关键点,要知道如何使用成员函数的指针
(this->objectPointer->*this->functionPointer)();
return 0;
}

调用的时候可以这样:
#include "MultiThread"
// ............
MultiThread::create(this, &MyClass::MyThread, "MyThread");
MultiThread::run("MyThread");
remove、exit、stop同理

==后记==
如果有不正确的地方欢迎指正w
不懂欢迎问ww
镇楼图和内容没半毛线关系【划掉
其实我只是水下经验,好久没冒泡应该没几个人记得我了www【划掉

0 0