当前位置: 首页 > news >正文

【UE5 C++课程系列笔记】25——多线程基础——FGraphEventRef的简单使用

目录

概念

使用示例1

使用示例2


概念

  FGraphEventRef 本质上是对一个异步任务或者一组相关异步任务在虚幻引擎任务图系统中的一种引用(reference)。虚幻引擎的任务图系统用于高效地调度和管理各种异步任务,协调它们的执行顺序以及处理任务之间的依赖关系等,而 FGraphEventRef 就是开发者与这个任务图系统交互的一个关键 “接口”,通过它可以实现对任务的创建、跟踪以及依赖管理等操作。

使用示例1

        先创建并执行一个简单的异步任务SimpleEvent等待其完成后,再批量创建 20 个异步任务存入 SimpleEventArray 中,最后等待这 20 个任务全部完成,以此体现任务图系统在协调多线程任务的执行顺序以及处理任务之间依赖关系的作用。

        代码如下所示:

void UThreadSubsystem::GraphEvent()
{FGraphEventRef SimpleEvent = FFunctionGraphTask::CreateAndDispatchWhenReady([this]() {PrintLogInThread(TEXT("SimpleEvent Start"));FPlatformProcess::Sleep(3);PrintLogInThread(TEXT("SimpleEvent End"));});check(!SimpleEvent->IsComplete());SimpleEvent->Wait();FGraphEventArray SimpleEventArray;for (size_t i = 0; i < 20; i++){SimpleEventArray.Add(FFunctionGraphTask::CreateAndDispatchWhenReady([this,i]() {FString Info1 = FString::Printf(TEXT("SimpleEvent Start -- %d"), i);PrintLogInThread(Info1);FPlatformProcess::Sleep(i%3);FString Info2 = FString::Printf(TEXT("SimpleEvent End -- %d"), i);PrintLogInThread(Info2);}));}FTaskGraphInterface::Get().WaitUntilTasksComplete(SimpleEventArray);
}void UThreadSubsystem::PrintLogInThread(FString Info)
{AsyncTask(ENamedThreads::GameThread, [Info]() {UE_LOG(LogTemp, Warning, TEXT("ThreadLog:[%s]"), *Info);});
}

        在第147行代码~151行代码中,通过 FFunctionGraphTask::CreateAndDispatchWhenReady 函数创建一个异步任务,并将返回的 FGraphEventRef 对象赋值给 SimpleEvent。在该异步任务的 lambda 表达式中,通过调用 FPlatformProcess::Sleep(3); 让线程休眠 3 秒来模拟任务执行过程中的耗时操作。

        第152行代码用于检查在创建任务后,任务是否立即就完成了(正常情况下刚创建的任务应该还未执行完,所以这里预期 IsComplete 返回 false),如果出现不符合预期的情况(即任务已经完成),check 宏会触发断言失败,有助于在开发阶段发现可能的逻辑错误。

        第153行代码调用 SimpleEvent->Wait(); 会使当前线程阻塞,一直等待这个异步任务执行完毕,确保后续代码在该任务完成后才继续执行,实现了简单的任务同步机制,保证了任务执行顺序上的先后关系。

        第155行代码创建了一个 FGraphEventArray 类型的数组 SimpleEventArray,用于存放多个 FGraphEventRef 对象,每个对象对应一个异步任务。

        第156~167行代码通过 for 循环创建20个异步任务

        第169行代码通过调用 FTaskGraphInterface::Get().WaitUntilTasksComplete(); 函数,让当前线程阻塞等待,直到 SimpleEventArray 数组中存放的所有 20 个异步任务都执行完毕,实现了对多个并行任务的同步等待功能。

        执行结果如下:

使用示例2

        该示例主要利用虚幻引擎的任务图系统来创建多个异步任务,并通过设置任务之间的依赖关系,实现特定的任务执行顺序。要实现的任务执行顺序如下图所示,我们需要先执行TaskA,TaskA执行完毕后开始同时执行TaskA1和TaskB,TaskB执行完毕后再执行TaskC,在TaskA1和TaskC都执行完毕的基础上再执行TaskD。

代码如下所示: 

void UThreadSubsystem::BatchGraphEvent()
{FGraphEventRef SimpleEventA = FFunctionGraphTask::CreateAndDispatchWhenReady([this]() {PrintLogInThread(TEXT("SimpleEventA Start"));FPlatformProcess::Sleep(3);PrintLogInThread(TEXT("SimpleEventA End"));});FGraphEventRef SimpleEventB = FFunctionGraphTask::CreateAndDispatchWhenReady([this]() {PrintLogInThread(TEXT("SimpleEventB Start"));FPlatformProcess::Sleep(3);PrintLogInThread(TEXT("SimpleEventB End"));}, TStatId{}, SimpleEventA);FGraphEventRef SimpleEventC = FFunctionGraphTask::CreateAndDispatchWhenReady([this]() {PrintLogInThread(TEXT("SimpleEventC Start"));FPlatformProcess::Sleep(3);PrintLogInThread(TEXT("SimpleEventC End"));}, TStatId{}, SimpleEventB);FGraphEventRef SimpleEventA1 = FFunctionGraphTask::CreateAndDispatchWhenReady([this]() {PrintLogInThread(TEXT("SimpleEventA1 Start"));FPlatformProcess::Sleep(3);PrintLogInThread(TEXT("SimpleEventA1 End"));}, TStatId{}, SimpleEventA);FGraphEventArray Prerequisite;Prerequisite.Add(SimpleEventA1);Prerequisite.Add(SimpleEventC);FGraphEventRef SimpleEventD = FFunctionGraphTask::CreateAndDispatchWhenReady([this]() {PrintLogInThread(TEXT("SimpleEventD Start"));FPlatformProcess::Sleep(3);PrintLogInThread(TEXT("SimpleEventD End"));}, TStatId{}, &Prerequisite);SimpleEventD->Wait();PrintLogInThread(TEXT("All Tasks Completed"));
}

        第174~178行代码创建了一个异步任务 SimpleEventA

        第180~184行代码创建了一个异步任务 SimpleEventB,并设置任务 SimpleEventB 设置了依赖于任务 SimpleEventA

        第186~190行代码创建了一个异步任务 SimpleEventC,并设置任务 SimpleEventC 设置了依赖于任务 SimpleEventB

        第192~196行代码创建了一个异步任务 SimpleEventA1,并设置任务 SimpleEventA1 设置了依赖于任务 SimpleEventA

        第198~206行代码首先创建了一个 FGraphEventArray 类型的数组 Prerequisite,并将SimpleEventA1和 SimpleEventC 这两个 FGraphEventRef 对象添加到其中,以此表示一组前置任务条件。然后创建任务 SimpleEventD 时,将 Prerequisite 作为参数传入,意味着SimpleEventD依赖于 SimpleEventA1 和 SimpleEventC 这两个任务,只有当这两个任务都执行完成后,SimpleEventD才会开始执行。 

        第208行代码通过调用 SimpleEventD->Wait(); 让当前线程阻塞等待,直到任务SimpleEventD执行完毕。由于 SimpleEventD 依赖于前面多个任务,所以实际上是等待整个任务链上的所有相关任务都完成后,此阻塞才会解除。

        执行结果如下:

如果要统计所有任务执行花费时间,可以通过添加如下代码实现

执行结果如下,总共花费12s,和预想的一样。

相关文章:

【UE5 C++课程系列笔记】25——多线程基础——FGraphEventRef的简单使用

目录 概念 使用示例1 使用示例2 概念 FGraphEventRef 本质上是对一个异步任务或者一组相关异步任务在虚幻引擎任务图系统中的一种引用&#xff08;reference&#xff09;。虚幻引擎的任务图系统用于高效地调度和管理各种异步任务&#xff0c;协调它们的执行顺序以及处理任务…...

计算机网络之---信号与编码

信号 在物理层&#xff0c;信号是用来传输比特流的物理量&#xff0c;它可以是电压、电流、光强度等形式&#xff0c;通常通过电缆、光纤或者无线信道等媒介传播。 信号主要分为以下两种类型&#xff1a; 模拟信号&#xff08;Analog Signal&#xff09;&#xff1a;信号在时间…...

linux下用命令行给串口写数据和读数据

在 Linux 系统中&#xff0c;串口设备&#xff08;如 /dev/ttyS3&#xff09;可以通过命令行进行读写操作。您遇到的问题是因为 Bash 解释了命令行中的字符串 “dis vlan\n”&#xff0c;但并没有按预期向串口设备发送数据。你应该将数据通过重定向发送到串口设备。 下面是如何…...

【生物信息】如何使用 h5py 读取 HDF5 格式文件中的数据并将其转换为 NumPy 数组

data_mat h5py.File(args.data_file) x1 np.array(data_mat[X1]) x2 np.array(data_mat[X2]) if not args.no_labels: y np.array(data_mat[Y]) data_mat.close() 这段代码展示了如何使用 h5py 读取 HDF5 格式文件中的数据并将其转换为 NumPy 数组。以下是代码的详细解释&a…...

纯手工(不基于maven的pom.xml、Web容器)连接MySQL数据库的详细过程(Java Web学习笔记)

1 引言 最近读一些Java Web开发类的书籍时&#xff0c;发现书中的连接数据库的过程缺少了一些关键性的过程&#xff0c;这对初学者非常不友好。为此&#xff0c;本文将给出详细的连接MySQL数据库的过程&#xff0c;并且是纯手工&#xff0c;不依赖于pom.xml和Web容器&#xff…...

thingsboard通过mqtt设备连接及数据交互---记录一次问题--1883端口没开,到服务器控制面板中打开安全组1883端口

1&#xff0c;链接不上&#xff1a;原因是1883端口没开&#xff0c;到服务器控制面板中打开安全组1883端口 2&#xff0c;参考链接&#xff1a; https://blog.csdn.net/bujingyun8/article/details/120024788...

联邦学习中的LoRA:FedLoRA

联邦学习中的LoRA:FedLoRA 联邦学习中的LoRA(Low-Rank Adaptation of Large Language Models)是一种用于在联邦学习场景下对大型语言模型进行低秩适应和高效微调的方法。以下是其原理及示例说明: 原理 低秩矩阵分解:在联邦学习中,通常会涉及到对预训练的大型模型进行微…...

PyTorch reshape函数介绍

torch.reshape 是 PyTorch 用于改变张量形状的函数之一。它不会改变张量的数据&#xff0c;而是重新组织其元素以适应新的形状。 reshape 的使用 torch.reshape(input, shape) → Tensorinput&#xff1a;输入张量。shape&#xff1a;新形状&#xff0c;使用整数或 -1 指定各维…...

Linux内核 -- 邮箱子系统之`mbox_controller` 的 `txdone_irq` 用法

Linux Kernel 中 mbox_controller 的 txdone_irq 用法 1. txdone_irq 的作用 txdone_irq 是一个布尔类型字段&#xff0c;用来指示邮件框控制器是否支持通过中断通知传输完成事件。 如果设置为 true&#xff1a; 硬件会在数据传输完成后生成中断。内核中相应的中断处理程序会…...

Linux/Ubuntu/银河麒麟 arm64 飞腾FT2000 下使用 arm64版本 linuxdeployqt 打包Qt程序

文章目录 一、前言二、环境三、准备1、下载Linuxdeployqt源码2、下载Appimagetool-aarch64.AppImage四、编译linuxdeployqt1.配置环境变量2.编译linuxdeployqt五、安装patchelf六、配置Appimagetool七、打包Qt程序重要提示:测试启动应用八、其他九、最后一、前言 因为项目需要…...

Excel | 空格分隔的行怎么导入excel?

准备工作&#xff1a;windows&#xff0c;一个记事本程序和微软的Excel软件。 打开记事本&#xff0c;选中所有内容&#xff0c;按CtrlA全选&#xff0c;然后复制(CtrlC)。 在Excel中&#xff0c;定位到你想粘贴的单元格&#xff0c;按CtrlV进行粘贴。粘贴后&#xff0c;你会在…...

如何将某两个提交去掉父提交的合并

q&#xff1a; 在一个两个月前的分支&#xff0c;我想保持纯净&#xff0c;但是需要把另一个变化很大的分支只将某两个提交的变更同步过来&#xff0c;基于idea的git操作该怎么做 a: 其实很多人会一下想到cherry pick&#xff0c;这个确实方便&#xff0c;但是会将父提交连带合…...

Windows下安装最新版的OpenSSL,并解决OpenSSL不是当前版本的问题,或者安装不正确的问题

文章目录 1. 文章引言1.1 需求描述1.2 简单介绍1.3 支持平台1.4 源码地址1.5 组件介绍2. 下载OpenSSL3. 安装OpenSSL5. 查看安装目录6. 解决OpenSSL的错误1. 文章引言 1.1 需求描述 今天接到一需求,解密php加密后的数据,由于php使用 openssl_encrypt的方式加密,java也需要使…...

Django 社团管理系统的设计与实现

标题:Django 社团管理系统的设计与实现 内容:1.摘要 本文介绍了 Django 社团管理系统的设计与实现。通过分析社团管理的需求&#xff0c;设计了系统的架构和功能模块&#xff0c;并使用 Django 框架进行了实现。系统包括社团信息管理、成员管理、活动管理、财务管理等功能&…...

android compose 串口通信

1.添加依赖 implementation("io.github.xmaihh:serialport:2.1.1") 2.添加SerialHelper派生类 class SerialPortHelper(portName:String,baudRate:Int): SerialHelper(portName,baudRate) {var receivedDataBuffer mutableListOf<Byte>()override fun onDa…...

Cursor无限续杯——解决Too many free trials.

前情提要 我们都知道Cursor对新用户是有14天且500条免费限制的。 一般情况下&#xff0c;当14天过期&#xff0c;是可以注销账户再重新注册&#xff0c;这样就可以继续拥有14天的体验时长。 但是&#xff01;&#xff01;如果使用超过500次&#xff0c;Cusor就会把你的电脑I…...

网络传输层TCP协议

传输层TCP协议 1. TCP协议介绍 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一个要对数据的传输进行详细控制的传输层协议。 TCP 与 UDP 的不同&#xff0c;在于TCP是有连接、可靠、面向字节流的。具体来说&#xff0c;TCP设置了一大…...

我的前端面试笔记(React篇)

1.React16 的 Fiber 是什么 fiber是react16的一种数据结构&#xff0c;用来描述每一个React 组件或 DOM 节点&#xff0c;并采用双向链表的存储结构。遍历节点的方式采用迭代遍历&#xff08;while循环&#xff09;&#xff0c;替代了以前的递归遍历。 fiber的优点 1&#xff…...

Qt 5.14.2 学习记录 —— 팔 QWidget 常用控件(3)

文章目录 1、cursor2、font3、toolTip4、focusPolicy5、styleSheeyt 1、cursor 改变鼠标光标形状。 在Qt Designer界面中&#xff0c;拖一个按钮过来&#xff0c;右边属性面用户可以自己改cursor属性。 代码方法&#xff0c;先拖一个按钮到界面上&#xff1a; #include <…...

HTTP协议和WebSocket协议

传统的HTTP协议是单向通信的&#xff0c;客户端若想要与服务器进行通信&#xff0c;首先需要通过三次握手与服务器建立TCP连接&#xff0c;然后再向服务器发送数据请求&#xff0c;当客户端收到服务器响应回来的数据后&#xff0c;就会断开TCP连接&#xff0c;每次数据请求都需…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...