ue4的多线程如何实现

19 篇文章 5 订阅

讲道理

一般要使用多线程技术的,就是该功能点费时,并且降低效率,阻碍体验。
就ue4来说,多线程一般用于后台的计算,信号的发送,检测等。
比如,通过开启一个线程进行心跳检测,确认码的发送。

实例

那么,在ue4中我们如何实现多线程呢?我们通过一个计算质数的功能来掩饰有无单线程的差别。

创建c++工程

在这里插入图片描述

新建一个FunctionLibrary

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在functionlibrary里编写三个函数,并且在cpp里面加以实现

/=================.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyBlueprintFunctionLibrary.generated.h"
/**
 *
 */
UCLASS()
class MULTITHREADTEST_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
       GENERATED_BODY()
public:
              UFUNCTION(BlueprintCallable, Category = "MultiThreadTest")
              static void MultiThreadDo(int32 MaxPrime);//多线程处理,参数用于计算质数
              UFUNCTION(BlueprintCallable, Category = "MultiThreadTest")
              static void SingleThreadDo(int32 MaxPrime);//单线程处理,参数用于计算质数
              static void Do(int32 MaxPrime);//处理调用,参数用于计算质数
};
/=================.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyBlueprintFunctionLibrary.h"
void UMyBlueprintFunctionLibrary::MultiThreadDo(int32 MaxPrime)
{
}
void UMyBlueprintFunctionLibrary::SingleThreadDo(int32 MaxPrime)
{
}
void UMyBlueprintFunctionLibrary::Do(int32 MaxPrime)
{

}

再创建一个空类

在这里插入图片描述
在这里插入图片描述

/=================.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
/**
 *
 */
class MULTITHREADTEST_API MyTaskClass
{
public:
       MyTaskClass();
       ~MyTaskClass();

};
/=================.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyTaskClass.h"
MyTaskClass::MyTaskClass()
{
}
MyTaskClass::~MyTaskClass()
{

}
  • 改写该类
/=================.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include <Runtime/Core/Public/Async/AsyncWork.h>
/**
 *
 */
class MULTITHREADTEST_API MyTaskClass :public FNonAbandonableTask
{
public:
       MyTaskClass();
       ~MyTaskClass();
       //该类必须要有的一个函数,用于生成标注生成线程的信息
       FORCEINLINE TStatId GetStatId() const
       {
              RETURN_QUICK_DECLARE_CYCLE_STAT(PrimeCalculationAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
       }
       void DoWork();//该方法继承与父类,在生成线程时会调用该方法进行执行任务
       int32 MaxPrime;//由于该方法不是静态方法,所以必须在生成该类的时候赋给我们需要的进行计算的值
       MyTaskClass(int32 MaxPrime);//补充一个构造函数用于赋值
};
/=================.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyTaskClass.h"
MyTaskClass::MyTaskClass()
{
}
MyTaskClass::~MyTaskClass()
{
}
void MyTaskClass::DoWork()
{
}
MyTaskClass::MyTaskClass(int32 MaxPrime)
{
       this->MaxPrime = MaxPrime;
}
  • 对functionlibrary进行补充,只在cpp文件进行改动
/=================.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyBlueprintFunctionLibrary.h"
#include "MyTaskClass.h"
void UMyBlueprintFunctionLibrary::MultiThreadDo(int32 MaxPrime)
{
       /*开启线程*/
       auto task = new FAutoDeleteAsyncTask<MyTaskClass>(MaxPrime);
       if (task)
              task->StartBackgroundTask();
       //通过阅读源码得知,该方式启用task,会自动新建一个线程,并且调用该类的dowork函数
}
void UMyBlueprintFunctionLibrary::SingleThreadDo(int32 MaxPrime)
{
       Do(MaxPrime);
}
void UMyBlueprintFunctionLibrary::Do(int32 MaxPrime)
{
       //Calculating the prime numbers...
       for (int32 i = 1; i <= MaxPrime; i++)
       {
              bool isPrime = true;
              for (int32 j = 2; j <= i / 2; j++)
              {
                     if (FMath::Fmod(i, j) == 0)
                     {
                           isPrime = false;
                           break;
                     }
              }
              if (isPrime)
                     GLog->Log("Prime number #" + FString::FromInt(i) + ": " + FString::FromInt(i));
       }
}
  • 对task进行补充,只在cpp文件进行改动
/=================.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyTaskClass.h"
#include "MyBlueprintFunctionLibrary.h"
MyTaskClass::MyTaskClass()
{
}
MyTaskClass::~MyTaskClass()
{
}
void MyTaskClass::DoWork()
{
       UMyBlueprintFunctionLibrary::Do(MaxPrime);
}
MyTaskClass::MyTaskClass(int32 MaxPrime)
{
       this->MaxPrime = MaxPrime;

对该项目在vs 上进行生成

在这里插入图片描述

创建测试用例

  • 接下来我们回到ue编辑器,新建一个actor
  • 在这里插入图片描述
  • 查找函数
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 把该actor拖入场景中,点击play,可以在日志里面看到计算结果的打印信息,也可以从界面上明显感受到两种方式的效果差。

结论

测试表明两者的差别主要是没有开启线程的程序,在程序运行时占用主线程导致主线程卡顿

### 回答1: 在UE4中,可以通过使用多线程来运行插件,以提高程序的性能和并行处理能力。 首先,插件在UE4中是以模块的形式存在的,可以独立于游戏项目而存在。为了实现多线程运行插件,可以在插件的模块中编写异步任务,利用多线程来执行这些任务。 在UE4中,我们可以使用FRunnable接口来创建自定义线程。首先,需要创建一个继承自FRunnable的类,并实现必要的接口函数,如Run和Stop。在Run函数中,编写插件需要执行的任务代码。 在插件的初始化阶段,可以通过调用FRunnableThread::Create函数来创建一个新的线程,并指定我们刚刚定义的FRunnable类对象作为参数。然后,可以开始执行插件任务。 需要注意的是,在多线程编程中,需要合理地处理线程之间的数据共享和同步问题。可以使用一些线程同步的机制,如互斥锁、信号量等,来避免多个线程同时操作共享数据导致的冲突。 另外,UE4还提供了一些已经封装好的多线程工具类,如FGraphEvent和FQueuedThread等,可以帮助我们更方便地实现多线程任务的管理和同步。 总结来说,UE4中可以通过使用FRunnable接口和多线程工具类来实现插件的多线程运行。合理地设计和管理多线程任务,可以提高程序的性能和并行处理能力,并且确保线程之间的数据共享和同步的正确性。 ### 回答2: 在UE4中,我们可以通过多线程实现插件的运行。多线程是一种并发执行任务的方式,可以让程序同时执行多个任务,提高了程序的效率和性能。 在UE4中,我们可以使用一些多线程的技术来实现插件的运行。比如,使用C++中的std::thread来创建多个线程,并让每个线程在后台执行插件相关的任务。同时,我们还可以使用一些线程同步的机制,比如互斥锁、条件变量等来管理多个线程之间的资源访问和共享。 在插件的运行过程中,可以将一些耗时的任务放在单独的线程中执行,这样就不会阻塞主线程的执行。比如,可以将插件中的某个算法或者处理逻辑放在一个独立的线程中运行,这样主线程可以继续执行其他的任务,提高了程序的响应速度和用户体验。 除了使用多线程,还可以使用UE4中提供的任务图谱系统来实现插件的并行执行。任务图谱系统可以将任务划分成多个小任务,并按照依赖关系进行调度,从而充分利用计算资源并提高任务执行的效率。 总结来说,UE4中可以通过多线程技术来实现插件的运行,可以提高程序的效率和性能,同时还可以使用任务图谱系统来实现任务的并行执行。这些技术可以充分发挥计算资源的利用率,提高插件的运行效果和用户体验。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值