ue4的多线程如何实现

讲道理

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

实例

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

创建c++工程

ue4的多线程如何实现

新建一个FunctionLibrary

ue4的多线程如何实现
ue4的多线程如何实现
ue4的多线程如何实现

在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)
{

}

再创建一个空类

ue4的多线程如何实现
ue4的多线程如何实现

/////////=================.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 上进行生成

ue4的多线程如何实现

创建测试用例

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

结论

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