在UE4中創(chuàng)建多線程

以下參考鏈接:https://wiki.unrealengine.com/index.php?title=Multi-Threading:_How_to_Create_Threads_in_UE4

以下是如何在UE4中創(chuàng)建線程,主要實(shí)現(xiàn)了:
  • 創(chuàng)建一個線程來計算前50000個素數(shù)。
  • 把計算完成的數(shù)據(jù)發(fā)送給主線程
  • 靜態(tài)函數(shù),用于啟動、關(guān)閉、查找線程是否已經(jīng)完成。
    這雖然是一個可行的方案,但是在創(chuàng)建許多任務(wù)時,可能會達(dá)到CPU可以處理的并發(fā)上限,此時并發(fā)線程實(shí)際上會在爭用CPU時間時相互阻礙。FQueuedThreadPool可以限制任務(wù)可用的線程數(shù)。
    .h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

/**
 * 
 */
class THREADPROJECT_API FPrimeNumberWorker : public FRunnable
{
    /** Singleton instance, can access the thread any time via static accessor, if it is active! */
    static  FPrimeNumberWorker* Runnable;

    /** Thread to run the worker FRunnable on */
    FRunnableThread* Thread;

    /** The Data Ptr */
    TArray<uint32>* PrimeNumbers;

    /** The PC */
    class AVictoryGamePlayerController* ThePC;

    /** Stop this thread? Uses Thread Safe Counter */
    FThreadSafeCounter StopTaskCounter;

    //The actual finding of prime numbers
    int32 FindNextPrimeNumber();

private:

    int32 PrimesFoundCount;

public:

    int32 TotalPrimesToFind;

    //判斷是否完成
    bool IsFinished() const
    {
        return PrimesFoundCount >= TotalPrimesToFind;
    }

    //~~~ Thread Core Functions ~~~

    //Constructor / Destructor
    FPrimeNumberWorker( TArray<uint32>& TheArray , const int32 IN_PrimesToFindPerTick ,class AVictoryGamePlayerController* IN_PC );
    virtual ~FPrimeNumberWorker();

    // Begin FRunnable interface.
    virtual bool Init();
    virtual uint32 Run();
    virtual void Stop();
    // End FRunnable interface

    /** 確保線程被正確的停止 */
    void EnsureCompletion();



    //~~~ 開啟,停止線程~~~



    /*
        Start the thread and the worker from static (easy access)!
        確保當(dāng)前只有一個 thread實(shí)例在運(yùn)行.
        This function returns a handle to the newly started instance.
    */
    static FPrimeNumberWorker* JoyInit( TArray<uint32>& TheArray , const int32 IN_TotalPrimesToFind , AVictoryGamePlayerController* IN_PC );

    /** 關(guān)閉線程,靜態(tài)函數(shù)可以方便在外面調(diào)用*/

    static void Shutdown();

    static bool IsThreadFinished();

    
    
    
    
};

.cpp

#include "FPrimeNumberWorker.h"
#include "ThreadingBase.h"
#include "VictoryGamePlayerController.h"


//***********************************************************
//Thread Worker Starts as NULL, prior to being instanced
//      This line is essential! Compiler error without it
FPrimeNumberWorker* FPrimeNumberWorker::Runnable = NULL;
//***********************************************************

FPrimeNumberWorker::FPrimeNumberWorker( TArray<uint32>& TheArray , const int32 IN_TotalPrimesToFind , AVictoryGamePlayerController* IN_PC )
    : ThePC( IN_PC ),
    TotalPrimesToFind( IN_TotalPrimesToFind )
    , StopTaskCounter( 0 )
    , PrimesFoundCount( 0 )
{
    //Link to where data should be stored
    PrimeNumbers = &TheArray;

    Thread = FRunnableThread::Create( this , TEXT( "FPrimeNumberWorker" ) , 0 , TPri_BelowNormal ); //windows default = 8mb for thread, could specify more
}

FPrimeNumberWorker::~FPrimeNumberWorker()
{
    delete Thread;
    Thread = NULL;
}

//Init
bool FPrimeNumberWorker::Init()
{
    //Init the Data 
    PrimeNumbers->Empty();
    PrimeNumbers->Add( 2 );
    PrimeNumbers->Add( 3 );

    if( ThePC )
    {
        ThePC->ClientMessage( "**********************************" );
        ThePC->ClientMessage( "Prime Number Thread Started!" );
        ThePC->ClientMessage( "**********************************" );
    }
    return true;
}

//Run
uint32 FPrimeNumberWorker::Run()
{
    //Initial wait before starting
    FPlatformProcess::Sleep( 0.03 );

    //確保沒有手動停止線程
    //      and 查找沒有完成
    while( StopTaskCounter.GetValue() == 0 && !IsFinished() )
    {
        PrimeNumbers->Add( FindNextPrimeNumber() );
        PrimesFoundCount++;

        //***************************************
        //Show Incremental Results in Main Game Thread!

        //  Please note you should not create, destroy, or modify UObjects here.
        //    Do those sort of things after all thread are completed.

        //    All calcs for making stuff can be done in the threads
        //       But the actual making/modifying of the UObjects should be done in main game thread.

        ThePC->ClientMessage( FString::FromInt( PrimeNumbers->Last() ) );

        //***************************************

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //prevent thread from using too many resources
        //FPlatformProcess::Sleep(0.01);
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }

    //Run FPrimeNumberWorker::Shutdown() from the timer in Game Thread that is watching
        //to see when FPrimeNumberWorker::IsThreadFinished()

    return 0;
}

//stop
void FPrimeNumberWorker::Stop()
{
    StopTaskCounter.Increment();
}

FPrimeNumberWorker* FPrimeNumberWorker::JoyInit( TArray<uint32>& TheArray , const int32 IN_TotalPrimesToFind , AVictoryGamePlayerController* IN_PC )
{
    //Create new instance of thread if it does not exist
    //      and the platform supports multi threading!
    if( !Runnable && FPlatformProcess::SupportsMultithreading() )
    {
        Runnable = new FPrimeNumberWorker( TheArray , IN_TotalPrimesToFind , IN_PC );
    }
    return Runnable;
}

void FPrimeNumberWorker::EnsureCompletion()
{
    Stop();
    Thread->WaitForCompletion();
}

void FPrimeNumberWorker::Shutdown()
{
    if( Runnable )
    {
        Runnable->EnsureCompletion();
        delete Runnable;
        Runnable = NULL;
    }
}

bool FPrimeNumberWorker::IsThreadFinished()
{
    if( Runnable ) return Runnable->IsFinished();
    return true;
}
int32 FPrimeNumberWorker::FindNextPrimeNumber()
{
    //Last known prime number  + 1
    int32 TestPrime = PrimeNumbers->Last();

    bool NumIsPrime = false;
    while( !NumIsPrime )
    {
        NumIsPrime = true;

        //Try Next Number
        TestPrime++;

        //Modulus from 2 to current number - 1 
        for( int32 b = 2; b < TestPrime; b++ )
        {
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //prevent thread from using too many resources
            //FPlatformProcess::Sleep(0.01);
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            if( TestPrime % b == 0 )
            {
                NumIsPrime = false;
                break;
                //~~~
            }
        }
    }

    //Success!
    return TestPrime;
}

需要創(chuàng)建線程時在可以在playerController里直接調(diào)用靜態(tài)函數(shù)JoyInit,停止調(diào)用shutDown。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對應(yīng)一個進(jìn)程,當(dāng)一個程序進(jìn)入內(nèi)存運(yùn)行時,即變成一個進(jìn)程.進(jìn)程是處于運(yùn)行過程中...
    勝浩_ae28閱讀 5,261評論 0 23
  • 線程 操作系統(tǒng)線程理論 線程概念的引入背景 進(jìn)程 之前我們已經(jīng)了解了操作系統(tǒng)中進(jìn)程的概念,程序并不能單獨(dú)運(yùn)行,只有...
    go以恒閱讀 1,805評論 0 6
  • 引言&動機(jī) 考慮一下這個場景,我們有10000條數(shù)據(jù)需要處理,處理每條數(shù)據(jù)需要花費(fèi)1秒,但讀取數(shù)據(jù)只需要0.1秒,...
    chen_000閱讀 589評論 0 0
  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對應(yīng)一個進(jìn)程,當(dāng)一個程序進(jìn)入內(nèi)存運(yùn)行時,即變成一個進(jìn)程.進(jìn)程是處于運(yùn)行過程中...
    小徐andorid閱讀 2,995評論 3 53
  • 租地還是5年前的事,母親在世的時候,在樓頭的空地扒拉一些石頭弄出一小塊地來種,也就栽點(diǎn)韭菜和大蔥而已。后來就去附近...
    長白王德軍閱讀 434評論 1 1

友情鏈接更多精彩內(nèi)容