AsyncTask

AsyncTask系统实现的多线程与自己实现继承的FRunnable实现的原理相似,还可以利用UE4提供的线程池。当使用多线程不满意时也可以调用StartSynchronousTask改成主线程执行。

来自头文件 AysncWork.h 文件中注释,直接仿照注释来实现AsyncTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
FAutoDeleteAsyncTask - template task for jobs that delete themselves when complete

Sample code:

class ExampleAutoDeleteAsyncTask : public FNonAbandonableTask
{
friend class FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>;

int32 ExampleData;

ExampleAutoDeleteAsyncTask(int32 InExampleData)
: ExampleData(InExampleData)
{
}

void DoWork()
{
... do the work here
}

FORCEINLINE TStatId GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(ExampleAutoDeleteAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
}
};


void Example()
{
// start an example job
(new FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>(5)->StartBackgroundTask();

// do an example job now, on this thread
(new FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>(5)->StartSynchronousTask();
}

代码实现:

继承FNonAbandonableTask创建一个线程类

在DoWork中实现需要实现的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// FTestAsyncTask.h 
#include "Async\AsyncWork.h"
#include "CoreMinimal.h"

class MX_API FTestAsyncTask : public FNonAbandonableTask
{
public:
friend class FAutoDeleteAsyncTask<FTestAsyncTask>;
int32 RunCount = 0;

FTestAsyncTask(FString ThreadName,class AActor1* a1) : MyThreadName(ThreadName), A1(a1) {};
~FTestAsyncTask();

void DoWork();

FORCEINLINE TStatId GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(FTestAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
}

FString MyThreadName;
class AActor1* A1;
static FCriticalSection CriticalSection;
};
///////////////////////////////////////////////////////////////////////
// FTestAsyncTask.cpp
FCriticalSection FTestAsyncTask::CriticalSection;

FTestAsyncTask::~FTestAsyncTask()
{

}

void FTestAsyncTask::DoWork()
{
UE_LOG(LogTemp, Log, TEXT("%s------%d"), *MyThreadName, RunCount);
while (IsValid(A1)) {
// 同步锁
FScopeLock Lock(&CriticalSection);
if (A1->TestCount < A1->TestTarget)
{
A1->TestCount++;
RunCount++;
// 节约资源 每100次打印一次
if (RunCount % 100 == 0)
UE_LOG(LogTemp, Log, TEXT("%s======%d"), *MyThreadName, RunCount);
}
else
{
break;
}
}

}

执行线程类:

1
2
3
4
5
6
7
8
// 头文件
int32 TestCount;

UPROPERTY(EditAnywhere)
int32 TestTarget;
// 线程运行
(new FAutoDeleteAsyncTask<FTestAsyncTask>("thread1", this))->StartBackgroundTask();
(new FAutoDeleteAsyncTask<FTestAsyncTask>("thread2", this))->StartBackgroundTask();

在自定义执行的线程类中 使用 FAutoDeleteAsyncTask 来传入我们刚才写的Task。FAutoDeleteAsyncTask顾名思义就是任务执行完就会自动删除

还有StartBackgroundTask和StartSynchronousTask的区别:

  • StartBackgroundTask会利用线程池里空闲的线程来执行。
  • StartSynchronousTask则是主线程执行。

执行结果:

LogTemp: thread2======30600
LogTemp: thread1======68000
LogTemp: thread1======68100
LogTemp: thread2======30700
LogTemp: thread2======30800
LogTemp: thread1======68200
LogTemp: thread1======68300
LogTemp: thread2======30900
LogTemp: thread2======31000
LogTemp: thread1======68400
LogTemp: thread1======68500
LogTemp: thread1======68600
LogTemp: thread1======68700
LogTemp: thread1======68800
LogTemp: thread2======31100
PIE: Play in editor total start time 0.055

这里运行次数设置的为100000 缺少一次是因为当满足条件是直接跳出了,没有打印出