日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

UE4多线程任务系统详解

發布時間:2023/12/10 windows 80 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UE4多线程任务系统详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先,了解一下該系統重要的數據類型.


1. FQueuedThreadPool:虛基類,隊列線程池,? FQueuedThreadPoolBase繼承自FQueuedThreadPool,
??? FQueuedThreadPoolBase維護了一個TArray<IQueuedWork*> QueuedWork(需要被執行的工作),? TArray<FQueuedThread*> AllThreads(所?????? 有的線程)
??? TArray<FQueuedThread*> QueuedThreads ( 空閑的線程)

2. FQueuedThread繼承自FRunnable,? 代表了線程的執行體,但并非線程本身。一個線程創建后將會執行FRunnable的Run()函數.
3. FRunnableThread代表了線程本身,該類會派生出平臺相關的子類,win32下對應的是FRunnableThreadWin,建議讀者看看某個平臺下的具體實???? 現。在創建時需要指定一個FRunnable,用于線程執行。
4. FEvent: 虛基類,提供了事件操作的接口,用于線程的激活掛起, 該類會派生出平臺相關的子類,win32下對應的是FEventWin。
??? 兩個重要接口: Wait()將會使線程掛起,Trigger()將會激活線程,配對使用。

了解了相關的數據類型后,可以開始剖析多線程任務系統的流程了,先從AsyncWork.h開始。
AsyncWork.h中有幾個使用多線程任務系統的例子,先來了解我們如何使用多線程來執行任務。

大體流程如下:?? ?
?? 先自定義一個任務類,用于執行我們的任務
?? class ExampleAutoDeleteAsyncTask : public FNonAbandonableTask
??? {
??????? friend class FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>;

??????? //核心接口,? 這里便是任務的具體執行內容.
??????? void DoWork()
??????? {?????????? ?
??????? }

??? };

//任務模板類,其作用是托管我們自定義的任務類,如執行完任務后自動銷毀.
template<typename TTask>
class FAutoDeleteAsyncTask : private IQueuedWork
{

??? TTask Task;
?? ?
??? //核心接口,任務的執行從這里開始, 參數bForceSynchronous = false表示異步執行
??? void Start(bool bForceSynchronous)
??? {
??????? FPlatformMisc::MemoryBarrier();
??????? FQueuedThreadPool* QueuedPool = GThreadPool;
??????? if (bForceSynchronous)
??????? {
??????????? QueuedPool = 0;
??????? }
?????? ?
??????? if (QueuedPool)
??????? {???? //異步執行,把自身(IQueuedWork)添加到隊列線程池中去執行
??????????? QueuedPool->AddQueuedWork(this);
??????? }
??????? else
??????? {
??????????? // 同步執行,直接調用Task.DoWork();
??????????? DoWork();
??????? }
??? }

??? void DoWork()
??? {
??????? Task.DoWork();
??????? delete this;
??? }

??? virtual void DoThreadedWork()
??? {
??????? DoWork();
??? }


??? void StartSynchronousTask()
??? {
??????? Start(true);
??? }


??? void StartBackgroundTask()
??? {
??????? Start(false);
??? }

};

??? //使用多線程任務的例子
??? void Example()
??? {
??????? //異步執行Task
??????? (new FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>(5)->StartBackgroundTask();
??????? //同步執行Task
??????? (new FAutoDeleteAsyncTask<ExampleAutoDeleteAsyncTask>(5)->StartSynchronousTask();
??? }

如何使用多線程來執行任務已經展示完了,就是這么easy!
接下來分析多線程來執行流程,重點是QueuedPool實例化時做了什么 以及 QueuedPool->AddQueuedWork(this);
我們先看一下QueuedPool實例是如何得到的:QueuedPool = GThreadPool;? 而GThreadPool是在引擎初始化的時候創建的,代碼在launchEngineLoop文件里,如下:
if (FPlatformProcess::SupportsMultithreading())
{??????? ?
??????? //可以看出,只有在系統支持多線程的情況下才會創建GThreadPool?? ?
??????? GThreadPool??? = FQueuedThreadPool::Allocate();
??????? int32 NumThreadsInThreadPool = FPlatformMisc::NumberOfWorkerThreadsToSpawn();
??????? verify(GThreadPool->Create(NumThreadsInThreadPool));
??????? 。。。。。。
}

GThreadPool? 創建之后便調用了它的Create
GThreadPool->Create(InNumQueuedThreads)
{
??????? // 主要是創建N個線程
??????? for (uint32 Count = 0; Count < InNumQueuedThreads && bWasSuccessful == true; Count++)
??????? {
??????????? FQueuedThread* pThread = new FQueuedThread();????????? ?
??????????? if (pThread->Create(this,StackSize,ThreadPriority) == true)
??????????? {
??????????????? QueuedThreads.Add(pThread);
??????????????? AllThreads.Add(pThread);
??????????? }
??????? }
??? 。。。。。。。?? ?
}

在FQueuedThread的Create接口里,創建了平臺相關的線程和系統事件,該線程的執行體是FQueuedThread的Run函數.
FQueuedThread::Create()
{
??????? DoWorkEvent = FPlatformProcess::GetSynchEventFromPool();
??????? Thread = FRunnableThread::Create(this, *PoolThreadName, InStackSize, ThreadPriority, FPlatformAffinity::GetPoolThreadMask());
??????? 。。。。。。。
}

Create()之后,線程執行了Run函數。
然而,在線程初始化之后,Run會一直處在while循環中,不斷等待DoWorkEvent->Trigger()
FQueuedThread::Run()
{
??????????? bool bContinueWaiting = true;
??????????? //在這個循環里,Wait()使線程不斷掛起.
??????????? while( bContinueWaiting )
??????????? {?????????????? ?
??????????????? bContinueWaiting = !DoWorkEvent->Wait( 10 );
??????????? }
??????????? 。。。。。。。
}

講到這里,先小結一下,實例化GThreadPool實際上也就是創建了N個線程,每個線程都處于一個不斷掛起,醒來,掛起的循環中。
這N個線程用于執行異步任務,用戶需要執行自定義的任務可以參考AsyncWork.h的例子。

那么,一定在某個地方會調用DoWorkEvent->Trigger()使Run能夠跳出死循環,執行后面的代碼。
聰明的讀者一定想到了在前面提到的 (GThreadPool等于QueuedPool)QueuedPool->AddQueuedWork(this), 沒錯,就是它,在AddQueuedWork里面便間接調用了DoWorkEvent->Trigger()

QueuedPool->AddQueuedWork(InQueuedWork)
{
??????? //取出一個空閑的線程執行InQueuedWork,沒有則添加到QueuedWork中
??????? if (QueuedThreads.Num() > 0)
??????? {
??????????? int32 Index = 0;
??????????? Thread = QueuedThreads[Index];
??????????? QueuedThreads.RemoveAt(Index);
??????? }
??????? if (Thread != nullptr)
??????? {
??????????? //DoWork實際上只是觸發了event,從而激活等待的線程
??????????? Thread->DoWork(InQueuedWork);
??????? }
??????? else
??????????? QueuedWork.Add(InQueuedWork);

}

FQueuedThread::DoWork(IQueuedWork* InQueuedWork)
{
??????? DoWorkEvent->Trigger();
}

調用DoWorkEvent->Trigger()之后,線程的Run()得以繼續執行,接下來的工作便是不斷取出Task來執行.
FQueuedThread::Run()
{
??????? 。。。。。。。。
??????????? IQueuedWork* LocalQueuedWork = QueuedWork??????? ?
??????????? while (LocalQueuedWork)
??????????? {
??????????????? //最終會執行Task.DoWork();
??????????????? LocalQueuedWork->DoThreadedWork();
??????????????? //取出下一個待執行的task或者把該FQueuedThread添加回空閑線程池中
??????????????? LocalQueuedWork = OwningThreadPool->ReturnToPoolOrGetNextJob(this);
??????????? }
?????? ?
}

至此,整個多線程任務的執行流程便分析完了!
---------------------
作者:子軒Q
來源:CSDN
原文:https://blog.csdn.net/tuanxuan123/article/details/52780629
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的UE4多线程任务系统详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。