【UE4 C++ 基础知识】<14> 多线程——AsyncTask
概念
AsyncTask
- AsyncTask 系统是一套基于线程池的异步任务处理系统。每创建一个AsyncTas,都会被加入到线程池中进行执行
- AsyncTask 泛指
FAsyncTask和FAutoDeleteAsyncTask,一般声明为友元函数,FNonAbandonableTask 派生类作为模板 FNonAbandonableTask是要继承的基类,不可被终止的任务,可以看作是任务执行体的抽象
FAsyncTask
- 模板类
DoWork()实现具体任务,自定义类作为模板参数- FAsyncTask 初始化后,默认添加到线程池FQueuedThreadPool。可以指定其他线程池
StartBackgroundTask()将任务扔到线程池中去执行StartSynchronousTask()直接在当前线程执行
EnsureCompletion()可以等待任务完成- 执行结束需要手动停止或删除任务
FAutoDeleteAsyncTask
- 与 FAsyncTask 类似
- 执行结束自动删除伍。执行完成后,会通过线程池的 Destroy 函数删除,或者 DoWork 完成后删除
FQueuedThreadPool线程池
- FQueuedThreadPool: 虚基类,定义线程池常用的接口。FQueueThreadPoolBase 继承FQueuedThreadPool,实现具体的方法。
- FQueueThreadPoolBase 维护了多个线程FQueuedThread与多个任务队列IQueuedWork
- TArray<IQueuedWork*> QueuedWork(要被执行的任务)
- TArray<FQueuedThread*> QueuedThreads(空闲的线程)
- TArray<FQueuedThread*> AllThreads(所有的线程)。
- 线程池里的线程都是FQueuedThread类型,FQueuedThread是继承自FRunnable的线程执行体
- FRunnableThread 表示线程本身,该类会派生出平台相关的子类
FEvent
- FEvent: 虚基类,提供了事件操作的接口,用于线程的挂起/唤醒(Wait()/Trigger())

使用方法
FNonAbandonableTask 与 FAsyncTask
SimpleAsyncTask 类
class SimpleAsyncTask :FNonAbandonableTask
{
FString m_TaskName;
int32 m_MaxNumber;
friend class FAsyncTask<SimpleAsyncTask>;
public:
// 构造函数
SimpleAsyncTask(const FString& TaskName, int32 MaxNumber)
: m_TaskName(TaskName), m_MaxNumber(MaxNumber) {}
// 析构函数
~SimpleAsyncTask()
{
UE_LOG(LogTemp, Warning, TEXT("Task[%s] End"), *m_TaskName);
} // 具体任务逻辑执行
void DoWork()
{
UE_LOG(LogTemp, Warning, TEXT("Task[%s] Start"), *m_TaskName);
int CurrentNum = 0;
while (CurrentNum < m_MaxNumber)
{
CurrentNum++;
UE_LOG(LogTemp, Warning, TEXT("Task[%s] CurrentNum:%d"), *m_TaskName, CurrentNum);
}
} // 固定写法,本类将作为函数参数
FORCEINLINE TStatId GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(SimpleAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
}
};
调用任务的Actor——AAsyncTaskActor
UFUNCTION(BlueprintCallable)
void CreateAsyncTask(const FString& TaskName, int32 MaxNumber);
void AAsyncTaskActor::CreateAsyncTask(const FString& TaskName, int32 MaxNumber)
{
UE_LOG(LogTemp, Warning, TEXT("Task[%s] Created"), *TaskName);
FAsyncTask<SimpleAsyncTask>* MyTask = new FAsyncTask<SimpleAsyncTask>(TaskName, MaxNumber);
MyTask->StartBackgroundTask(); // MyTask->StartSynchronousTask; 在当前线程执行,可能会导致主线程阻塞
// MyTask->IsDone() 可以配合定时器检测是否完成任务 //等待任务完成后,进行手动删除
MyTask->EnsureCompletion();
delete MyTask;
MyTask = nullptr;
}
FNonAbandonableTask 与 FAutoDeleteAsyncTask
AutoDeleteSimpleAsyncTask 类
class AutoDeleteSimpleAsyncTask :FNonAbandonableTask
{
FString m_TaskName;
int32 m_MaxNumber;
friend class FAutoDeleteAsyncTask<AutoDeleteSimpleAsyncTask>;
public:
// 构造函数
AutoDeleteSimpleAsyncTask(const FString& TaskName, int32 MaxNumber)
: m_TaskName(TaskName), m_MaxNumber(MaxNumber) {}
// 析构函数
~AutoDeleteSimpleAsyncTask()
{
UE_LOG(LogTemp, Warning, TEXT("Task[%s] End"), *m_TaskName);
} // 具体任务逻辑执行
void DoWork()
{
UE_LOG(LogTemp, Warning, TEXT("Task[%s] Start"), *m_TaskName);
int CurrentNum = 0;
while (CurrentNum < m_MaxNumber)
{
CurrentNum++;
UE_LOG(LogTemp, Warning, TEXT("AutoDeleteTask[%s] CurrentNum:%d"), *m_TaskName, CurrentNum);
}
} // 固定写法,本类将作为函数参数
FORCEINLINE TStatId GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(SimpleAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
}
};
调用任务的Actor——AAsyncTaskActor
UFUNCTION(BlueprintCallable)
void CreateAutoDeleteAsyncTask(const FString& TaskName, int32 MaxNumber);
void AAsyncTaskActor::CreateAutoDeleteAsyncTask(const FString& TaskName, int32 MaxNumber)
{
UE_LOG(LogTemp, Warning, TEXT("AutoDeleteTask[%s] Created"), *TaskName);
// 任务完成后,自动删除
(new FAutoDeleteAsyncTask<AutoDeleteSimpleAsyncTask>(TaskName, MaxNumber))->StartSynchronousTask();
}

参考
- FAsyncTask
- FAutoDeleteAsyncTask
- FNonAbandonableTask
- Legacy/Using AsyncTasks
- 《Exploring in UE4》多线程机制详解[原理分析]
- \EpicGames\UE_4.26\Engine\Source\Runtime\Core\Public\Async\AsyncWork.h
【UE4 C++ 基础知识】<14> 多线程——AsyncTask的更多相关文章
- 【UE4 C++ 基础知识】<11>资源的同步加载与异步加载
同步加载 同步加载会造成进程阻塞. FObjectFinder / FClassFinder 在构造函数加载 ConstructorHelpers::FObjectFinder Constructor ...
- 【UE4 C++ 基础知识】<12> 多线程——FRunnable
概述 UE4里,提供的多线程的方法: 继承 FRunnable 接口创建单个线程 创建 AsyncTask 调用线程池里面空闲的线程 通过 TaskGraph 系统来异步完成一些自定义任务 支持原生的 ...
- 【UE4 C++ 基础知识】<3> 基本数据类型、字符串处理及转换
基本数据类型 TCHAR TCHAR就是UE4通过对char和wchar_t的封装 char ANSI编码 wchar_t 宽字符的Unicode编码 使用 TEXT() 宏包裹作为字面值 TCHAR ...
- 【UE4 C++ 基础知识】<13> 多线程——TaskGraph
概述 TaskGraph 系统是UE4一套抽象的异步任务处理系统 TaskGraph 可以看作一种"基于任务的并行编程"设计思想下的实现 通过TaskGraph ,可以创建任意多线 ...
- JAVA基础知识之多线程——三种实现多线程的方法及区别
所有JAVA线程都必须是Thread或其子类的实例. 继承Thread类创建线程 步骤如下, 定义Thead子类并实现run()方法,run()是线程执行体 创建此子类实例对象,即创建了线程对象 调用 ...
- java基础知识总结--多线程
1.扩展Java.lang.Thread类 1.1.进程和线程的区别: 进程:每个进程都有自己独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1~n个线程. 线程:同一类线 ...
- 【UE4 C++ 基础知识】<5> 容器——TArray
概述 TArray 是UE4中最常用的容器类.其速度快.内存消耗小.安全性高. 其设计时未考虑扩展问题,因此建议在实际操作中勿使用 新建(new) 和 删除(delete) 创建或销毁 TArray ...
- 【UE4 C++ 基础知识】<8> Delegate 委托
概念 定义 UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系. 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到 ...
- JAVA基础知识之多线程——线程组和未处理异常
线程组 Java中的ThreadGroup类表示线程组,在创建新线程时,可以通过构造函数Thread(group...)来指定线程组. 线程组具有以下特征 如果没有显式指定线程组,则新线程属于默认线程 ...
随机推荐
- 【曹工杂谈】详解Maven插件调试方法
前言 今年的更新频率简直是降至冰点了,一方面平时加班相对多一些了,下班只想玩手机:另一方面,好像进了大厂后,学习动力也很低了,总之就,很懒散,博客的话,今年都才只更新了不到5篇. 现在慢慢有一点状态, ...
- 免费 CDN 玩法 —— 将整个网站打包成一个图片文件
资源合并 前端开发者都知道,过多的请求对性能影响很大.而且有些 CDN 不仅按流量收费,请求数也收费,如果网页里有大量小文件,显然不划算. 为此不少开发者将零碎的小文件进行合并优化,例如 JS/CSS ...
- 内核软中断之tasklet机制
1. 软中断IRQ简介 软中断(SoftIRQ)是内核提供的一种基于中断的延时机制, Linux内核定义的软中断有以下几种: enum { HI_SOFTIRQ=0, /*高优先级的tasklet*/ ...
- BFD协议简介
1. 背景 双向转发检测BFD(Bidirectional Forwarding Detection)是一种全网统一的检测机制,用于快速检测.监控网络中链路或者IP路由的转发连通状况. 为了保护关键应 ...
- CSS滤镜让图片模糊(毛玻璃效果)
CSS代码: .blur { filter: url(blur.svg#blur); /* FireFox, Chrome, Opera */ -webkit-filter: blur(10px); ...
- Spring全自动AOP和项目加入jar包
一.jar可以引进项目中,复制到路下后,要add as library,加载到工作空间中才能引入: 也jar包放在硬盘的项目目录外面,可以多个项目引入共用: 二.xml配置 1.aop全自动配置 2. ...
- 路由懒加载---Vue Router
一.什么是懒加载? 懒加载也就是延迟加载或者按需加载,即在需要的时候进行加载. 二.为什么在Vue路由中使用懒加载? 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常 ...
- HDU 6170 FFF at Valentine(强联通缩点+拓扑排序)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6165 题意:给你一个无环,无重边的有向图,问你任意两点,是否存在路径使得其中一点能到达另一点 解析:强 ...
- html jquey的选择器checkbox,select
1 判断checkbox是否选中 用到 jquery的 is方法 jquery: <div id="divId" class="divTable"> ...
- oracle 基础SQL语句 增删改
一.SQL操作 查询已创建的数据库:SELECT datname FROM pg_database; 创建数据库:CREATE DATABASE wzxdb; 删除数据库:DROP DATABASE ...