蓝图
当点击按钮时,创建一个LsqAsyncStudyActor,并且绑定到OnAsyncSuccess委托事件,然后调用DoAsync函数。OnAsyncSuccess委托事件是给FRunnable活干完了通知主线程的回调用的。
LsqAsyncStudyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "LsqAsyncStudyActor.generated.h"
UCLASS()
class TESTCLIENT0926_API ALsqAsyncStudyActor : public AActor
{
GENERATED_BODY()
public:
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FAsyncSuccessDelegate);
UFUNCTION(BlueprintCallable, Category = "LsqNet")
void DoAsync();
UPROPERTY(BlueprintAssignable)
FAsyncSuccessDelegate OnAsyncSuccess;
protected:
class LsqAsyncStudyThread1* MyThread; //使用前向声明法 来解决 头文件循环包含bug
};
LsqAsyncStudyActor.cpp
#include "LsqAsyncStudyActor.h"
#include "LsqAsyncStudyThread1.h" //使用前向声明法 解决 头文件循环包含bug
void ALsqAsyncStudyActor::DoAsync() {
// 实例化LsqAsyncStudyThread1对象,并将ALsqAsyncStudyActor对象作为参数传递
MyThread = new LsqAsyncStudyThread1(this);
// 启动线程
FRunnableThread::Create(MyThread, TEXT("LsqAsyncStudyThread1"));
}
在DoAsync里面,先new一个线程对象LsqAsyncStudyThread1,这个线程对象是我自定义的,实现了FRunnable接口的。
然后调用FRunnableThread的Create静态方法启动线程。
为什么要用UE的这套方法来创建线程和启动线程呢?一是使用了UE的跨平台特性,二是由引擎去完成线程的管理细节。
LsqAsyncStudyThread1.h
#pragma once
#include "CoreMinimal.h"
#include "LsqAsyncStudyActor.h"
#include "HAL/Runnable.h"
#include "HAL/RunnableThread.h"
class TESTCLIENT0926_API LsqAsyncStudyThread1:public FRunnable
{
public:
LsqAsyncStudyThread1(ALsqAsyncStudyActor* InActor);
~LsqAsyncStudyThread1();
virtual bool Init() override;
virtual uint32 Run() override;
virtual void Stop() override;
virtual void Exit() override;
private:
ALsqAsyncStudyActor* MyActor;
};
FRunnable有四大函数
virtual bool Init() override;
virtual uint32 Run() override;
virtual void Stop() override;
virtual void Exit() override;
正常流程下,它会依次执行 Init,Run,Exit三个函数
在Run里面写你需要多线程的业务逻辑。
我这里使用的是 FPlatformProcess::Sleep(5.0f);
让这个线程睡上五秒,模拟费时的操作
在操作完了,我还BroadCast了Actor的完成事件 MyActor->OnAsyncSuccess.Broadcast();
使用UE的委托与事件的方式,通知调用者异步任务已经完成,可以过来取结果了
LsqAsyncStudyThread1.cpp
#include "LsqAsyncStudyThread1.h"
LsqAsyncStudyThread1::LsqAsyncStudyThread1(ALsqAsyncStudyActor* InActor)
{
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::White, "Thread Construct");
MyActor = InActor;
}
LsqAsyncStudyThread1::~LsqAsyncStudyThread1()
{
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::White, "Thread Destruct");
}
bool LsqAsyncStudyThread1::Init() {
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::White, "Thread Init");
return true;
}
uint32 LsqAsyncStudyThread1::Run() {
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::White, "Thread Run");
FPlatformProcess::Sleep(5.0f);
MyActor->OnAsyncSuccess.Broadcast();
return 0;
}
void LsqAsyncStudyThread1::Stop(){
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::White, "Thread Stop");
}
void LsqAsyncStudyThread1::Exit() {
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::White, "Thread Exit");
}
输出结果:
如果改一下Exit
void LsqAsyncStudyThread1::Exit() {
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::White, “Thread Exit”);
delete this;//在线程结束时销毁对象
}