AceHigh
(AceHigh)
August 3, 2022, 9:59pm
1
Hi there. I was wondering if there are any good tutorials on how to get started with multithreading in ue5. The problem I’m having is when I run 2 threads concurrently like:
MyThread x(1);
MyThread y(2);
I get the following output:
Running thread 1
1
2
3
4
Exited
Running thread 2
1
2
3
4
shouldn’t there be some overlap here?
zos
(Andrew Tomazos)
August 3, 2022, 10:55pm
2
It would be helpful to show the definition of MyThread.
AceHigh
(AceHigh)
August 3, 2022, 11:00pm
3
class CHESSCODE_API MyThread : public FRunnable
{
public:
MyThread(int threadCount);
~MyThread();
virtual uint32 Run() override;
virtual void Stop() override;
virtual void Exit() override;
virtual bool Init() override;
int th;
//FMyThreadOnCompleteSignature OnCompleteDelegate;
protected:
FRunnableThread* Thread = nullptr;
TArray<int32> ProcessedNumbers;
int32 TargetCount = -1;
int32 FoundCount = -1;
bool bStopThread = false;
};
zos
(Andrew Tomazos)
August 3, 2022, 11:03pm
4
And the definitions of the constructor and member functions.
AceHigh
(AceHigh)
August 3, 2022, 11:04pm
5
bool MyThread::Init() {
return false;
}
MyThread::MyThread(int threadCount)
{
th = threadCount;
TargetCount = 10;
FoundCount = 0;
Thread = FRunnableThread::Create(this, TEXT("Thread") + th);
}
MyThread::~MyThread()
{
if (Thread != nullptr) {
Thread->Kill(true);
delete Thread;
}
}
uint32 MyThread::Run()
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("running thread " + FString::FromInt(th)));
UE_LOG(LogTemp, Warning, TEXT("running thread %d"), th);
bStopThread = false;
while (!bStopThread && FoundCount < TargetCount) {
if (FoundCount == 2) {
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("break"));
UE_LOG(LogTemp, Warning, TEXT("break"));
//Stop();
}
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("fc = " + FString::FromInt(FoundCount)));
UE_LOG(LogTemp, Warning, TEXT("fc = %d"), FoundCount);
int32 x = 0;
while (x < INT_MAX)
{
x++;
}
ProcessedNumbers.Add(FMath::RandRange(0, 999));
FoundCount += 1;
}
//OnCompleteDelegate.ExecuteIfBound();
return 0;
}
void MyThread::Exit()
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("exit"));
UE_LOG(LogTemp, Warning, TEXT("exit"));
}
void MyThread::Stop()
{
bStopThread = true;
}
zos
(Andrew Tomazos)
August 3, 2022, 11:08pm
6
Print out IsInGameThread()
in Run()
zos
(Andrew Tomazos)
August 3, 2022, 11:10pm
8
I suspect Run is running in game thread. Check this by calling IsInGameThread()
and logging the return value.
AceHigh
(AceHigh)
August 3, 2022, 11:16pm
9
Yes IsInGameThread()
returned true
zos
(Andrew Tomazos)
August 3, 2022, 11:17pm
10
Yeah I had a hunch. I’ll have a look in a minute, I havent used unreal threads before.
zos
(Andrew Tomazos)
August 3, 2022, 11:23pm
12
Try setting a breakpoint on Run and then execute in your IDE debugger. Check whats on the stack when run is called.
zos
(Andrew Tomazos)
August 3, 2022, 11:27pm
13
Also I think this thread name is wrong. I think you’re doing pointer arithmetic on the string literal which is not what you intend. I think you want to create an FString member with FString::Printf and then call (*name) to pass it. (but this is likely unrelated to the issue you are encountering)
AceHigh
(AceHigh)
August 3, 2022, 11:31pm
14
I’m not comfortable with breakpoints. I am using the latest Visual Studio though.
AceHigh
(AceHigh)
August 3, 2022, 11:57pm
15
Also: Have Confirmed that using if (th == 1) FPlatformProcess::Sleep(2.0);
stalls both threads. In fact if (th == 2) FPlatformProcess::Sleep(2.0);
stalls both threads.
zos
(Andrew Tomazos)
August 4, 2022, 12:17am
16
I suggest you prioritize learning how to use breakpoints ahead of learning how to use threads.
Learn about breakpoints, one of the most important debugging techniques. The article covers breakpoint actions, tracepoints, conditions, and much more.
AceHigh
(AceHigh)
August 4, 2022, 12:42am
17
Thanks for the tip. I am now comfortable with breakpoints. What should I be looking for? I break at Run()
and I get a bunch of information. However, after I passed through the breakpoint both times all the on screen debug messages get flushed to the screen. What could this mean?
If a thread is just printing 4 numbers there probably won’t any overlap because that literally takes no time. Print a few thousand items and see if there is overlap. Also you could Sleep(1) after every iteration.
zos
(Andrew Tomazos)
August 4, 2022, 4:49am
19
When you break on the Run function look at the call stack that is calling your Run function. Copy and paste the call stack into this discussion.
zos
(Andrew Tomazos)
August 4, 2022, 4:50am
20
IsInGameThread()
returns true, so that means his Run()
function is being called on the game thread and not on new unique threads, right?