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

news2025/1/12 3:49:00

目录

概念

使用示例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,和预想的一样。

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

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

相关文章

DeepSeek:性能强劲的开源模型

deepseek 全新系列模型 DeepSeek-V3 首个版本上线并同步开源。登录官网 chat.deepseek.com 即可与最新版 V3 模型对话。 性能对齐海外领军闭源模型​ DeepSeek-V3 为自研 MoE 模型&#xff0c;671B 参数&#xff0c;激活 37B&#xff0c;在 14.8T token 上进行了预训练。 论…

使用 SQL 和表格数据进行问答和 RAG(1)—数据库准备

一. 从 .sql/csv/xlsx 文件创建 sqlite 数据库。 要从.sql文件准备 SQL DB&#xff0c;这里会将创建数据库的代码放到了&#xff0c;将文件复制到data/sql目录中&#xff0c;然后在终端中的项目文件夹中执行&#xff1a; pip install sqlite3现在创建一个名为sqldb的数据库&a…

用否定法去跳脱圈层

在这个充满竞争和诱惑的时代&#xff0c;许多人发现自己被困在了一个看似舒适却实则束缚重重的圈层之中。这个圈层&#xff0c;可能是由底层人的思维惯性、不良习惯、无谓消费、攀比心理等构成的。要真正实现自我提升&#xff0c;跳出这个圈层&#xff0c;就需要我们运用否定法…

C++类的引入

C中类的前身 1> 面向对象三大特征&#xff1a;封装、继承、多态 2> 封装&#xff1a;将能够实现某一事物的所有万事万物都封装到一起&#xff0c;包括成员属性&#xff08;成员变量&#xff09;&#xff0c;行为&#xff08;功能函数&#xff09;都封装在一起&#xff…

Postman配置环境变量

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Postman是一套比较方便的接口测试工具&#xff0c;但我们在使用过程中&#xff0c;可能会出现创建了API请求&#xff0c;但API的URL会随着服务器IP地址的变化而改…

新能源网站提升用户体验的关键

新能源网站的用户体验对于吸引和留住访问者至关重要。一个优秀的用户体验可以增加用户的满意度&#xff0c;提高他们对网站的忠诚度。在设计新能源网站时&#xff0c;关键在于简洁明了的界面和易于导航的布局。用户应该能够轻松找到他们需要的信息&#xff0c;而不会感到困惑或…

【Unity3D日常开发】Unity3D中适用WEBGL打开Window文件对话框打开/上传文件

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享QQ群&#xff1a;398291828小红书小破站 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 Unity3D发布的WEBGL程序是不支持直接的I/O操…

ElasticSearch内存占用率过高怎么办?

文章目录 1&#xff0c;先用top看看各个进程的内存占用情况2&#xff0c;不能简单的杀死进程&#xff0c;然后再重启。3&#xff0c;查看一下ElasticSearch进程的具体启动情况4&#xff0c;修改Elasticsearch 的Java堆内存 1&#xff0c;先用top看看各个进程的内存占用情况 先…

DC/AC并网逆变器模型与仿真MATLAB

DC/AC并网逆变器是一种将直流电&#xff08;DC&#xff09;转化为交流电&#xff08;AC&#xff09;&#xff0c;并将其与电网并联的设备。它的核心功能是实现直流电源&#xff08;如光伏电池板或储能电池&#xff09;与电网的有效连接&#xff0c;同时保证输出电能质量满足电网…

Flink三种集群部署模型

这里写自定义目录标题 Flink 集群剖析Flink 应用程序执行Flink Session 集群&#xff08;Session Mode&#xff09;Flink Job 集群&#xff08;以前称为per-job&#xff09;Flink Application 集群&#xff08;Application Mode&#xff09; 参考 Flink 集群剖析 Flink 运行时…

JVM实战—12.OOM的定位和解决

大纲 1.如何对系统的OOM异常进行监控和报警 2.如何在JVM内存溢出时自动dump内存快照 3.Metaspace区域内存溢出时应如何解决(OutOfMemoryError: Metaspace) 4.JVM栈内存溢出时应如何解决(StackOverflowError) 5.JVM堆内存溢出时应该如何解决(OutOfMemoryError: Java heap s…

一文读懂「LoRA」:大型语言模型的低秩适应

LoRA: Low-Rank Adaptation of Large Language Models 前言 LoRA作为大模型的微调框架十分实用&#xff0c;在LoRA出现以前本人都是通过手动修改参数、优化器或者层数来“炼丹”的&#xff0c;具有极大的盲目性&#xff0c;但是LoRA技术能够快速微调参数&#xff0c;如果LoRA…

IT面试求职系列主题-人工智能(一)

想成功求职&#xff0c;必要的IT技能一样不能少&#xff0c;再从人工智能基础知识来一波吧。 1&#xff09;您对人工智能的理解是什么&#xff1f; 人工智能是计算机科学技术&#xff0c;强调创造能够模仿人类行为的智能机器。这里智能机器可以定义为能够像人一样行动、像人一…

浏览器报错:您的连接不是私密连接,Kubernetes Dashboard无法打开

问题描述 部署完成Kubernetes Dashboard后&#xff0c;打开HTTPS的web页面&#xff0c;Chrome和Edge浏览器都无法正常加载页面&#xff0c;会提示您的连接不是私密连接的报错。 ​​​​​​​​​​​​ 原因&#xff1a; 浏览器不信任这些自签名的ssl证书&#xff0c;为了…

【Unity插件】解决移动端UI安全区问题 - Safe Area Helper

在移动端设计界面时&#xff0c;必须要考虑的就是UI的安全区。 Unity本身也提供了Safearea的API。 但在asset store时已经有人提供了免费的插件&#xff08;Safe Area Helper&#xff09;&#xff0c;我们可以直接使用。 插件链接&#xff1a; https://assetstore.unity.com/p…

ffmpeg7.0 aac转pcm

#pragma once #define __STDC_CONSTANT_MACROS #define _CRT_SECURE_NO_WARNINGSextern "C" { #include "libavcodec/avcodec.h" }//缓冲区大小&#xff08;缓存5帧数据&#xff09; #define AUDIO_INBUF_SIZE 40960 /*name depthu8 8s16 …

USRP X310 Windows 烧录镜像

说明 USRP-X 系列设备包含两个用于两个以太网通道的 SFP 端口。由于 SFP 端口支持 1 千兆 (SFP) 和 10 千兆 (SFP) 收发器&#xff0c;因此 UHD 附带了多个 FPGA 图像&#xff0c;以确定上述接口的行为。 注意&#xff1a;Aurora 图像需要从 FPGA 源代码手动构建。 FPGA 图像…

新型物联网智能断路器功能参数介绍

安科瑞刘鸿鹏 摘要 智能断路器作为现代配电系统的重要组成部分&#xff0c;以其实时监测、多重保护和远程操控的智能化功能&#xff0c;显著提升了电力系统的运行效率和安全性。本文以ASCB1系列智能断路器为例&#xff0c;探讨其技术特点和在工业、商业及民用建筑中的应用价…

119.使用AI Agent解决问题:Jenkins build Pipeline时,提示npm ERR! errno FETCH_ERROR

目录 1.Jenkins Build时的错误 2.百度文心快码AI智能体帮我解决 提问1&#xff1a;jenkins中如何配置npm的源 提问2&#xff1a;jenkins pipeline 类型为pipeline script from SCM时&#xff0c;如何配置npm源 3.最终解决方法-Jenkinsfile的修改 4.感触 1.Jenkins Build时…

pytest+allure 入门

使用allure如何生成自动化测试报​​​​​​告 &#xff1f;一文详解allure的使用 。_allure测试报告-CSDN博客 例子&#xff1a; import allure import pytest import osallure.epic("闹钟") allure.feature("闹钟增删") class TestSchedule():def setu…