Can you elaborate? How do you “message” game thread to create AActors, for example? Is there a pipe/stream messaging API already built-in ue4, or are you making your own?
I built for my projects a class with static mechanisms and static delegates that can be linked from AsyncTasks using “FSimpleDelegate::CreateStatic” like Mike Preussner suggested we should do in this same thread.
There’s usage samples in engine code, they are really simple to use together with AsyncTasks.
They wrap parameters into structs and send them to “named” Game Thread, but I usually send object pointers instead because I need access to UProperty* objects (when I read/write user defined blueprint structs or create new UObjects within the DoWork() function.
I use a simple bool set/reset in DoWork() what can be checked in the caller class when it has a tick function, probably not the most elegant but works.
As an example, I reworked a plugin to make cover calculations async:
https://github.com/s-ivan/CoverGener…oversAsync.cpp
An example of using delegates would be cool. Probably I could do it, if I were not so lazy…
bump
Error
- Please enter a message with at least 10 characters (please_enter_message_x_chars)
Any update on the continuations?
I was just doing some async work with this and noticed continuations seem to be working, though I have no idea when they were added. Potentially years ago. I could not find any documentation or usage examples anywhere.
But something like this worked for me:
TFuture<void> SlowTaskAsync()
{
return Async(EAsyncExecution::TaskGraph,[]()
{
ExecuteSlowTask();
}).Then([](auto Future)
{
DoSomethingElseAfterward();
});
}
The continuation takes the previous (completed) future as a parameter and creates its own future from the Then() call. (If the continuation code returned an int32 in the above code, you could have the outer SlowTaskAsync function return a TFuture, even though the main task body itself creates a TFuture in this case)
However, it’s important to know that the continuation also runs on the same thread as the original task (I think). If you wanted to continue on the main thread, you could await another async call back to the main thread within the continuation, but then you’d have to be careful that any code calling SlowTaskAsync in this exmaple doesn’t await it from the main thread otherwise it’ll cause a deadlock. Not sure if there’s a way around this.
Hi, hope all of you are doing very well. I’m very new to multi-threading in c++ and in UE. Would you be so kind to look at my code and tell me what I do wrong or how I misuse API. I have nothing wrong with my code behaviour yet it is an insecurity call to post here.
> bool UEthernetSightswarm::EstablishConnection()
> {
> connectionAttmpts++;
> FIPv4Address address;
> FIPv4Address::Parse(IP, address);
> FIPv4Endpoint Endpoint(address, defaultPort);
> socket = FTcpSocketBuilder(TEXT("TcpSocket")).AsReusable().Build();
> ISocketSubsystem* socketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
> bool res = socket->Connect(*socketSubsystem->CreateInternetAddr(Endpoint.Address.Value, Endpoint.Port));
> UE_LOG(LogTemp, Warning, TEXT("Connecting attempt is %s"), res ? *FString("sucssess") : *FString("unsucssess"));
> double start = world->TimeSeconds;
>
> if (res)
> {
> FutureThread = Async(EAsyncExecution::Thread, [this, start]()
> {
> double since = 0.f;
> while (since < timeout && socket->GetConnectionState() != ESocketConnectionState::SCS_Connected && isRunning)
> {
> since = world->TimeSince(start);
> OnTestRecived.Broadcast(since);
> //UE_LOG(LogTemp, Warning, TEXT("%f"), since);
> FPlatformProcess::Sleep(0.5f);
> }
>
> if(isRunning)
> OnConnectionAttempt.Execute(socket->GetConnectionState() == ESocketConnectionState::SCS_Connected);
>
> return;
> });
> }
> else
> {
> FutureThread = Async(EAsyncExecution::Thread, [this]()
> {
> FPlatformProcess::Sleep(0.5f);
> OnConnectionAttempt.Execute(false);
> return;
> });
> }
>
> return res;
> }
>
> void UEthernetSightswarm::ConnectionResponce(bool isConnected)
> {
> if (FutureThread.IsValid() && FutureThread.IsReady())
> FutureThread.Get();
>
> FFunctionGraphTask::CreateAndDispatchWhenReady([this, isConnected]()
> {
> // This code is on game thread
> if (isConnected)
> OnConnectionEstablished.Broadcast();
> else
> {
> if (connectionAttmpts > maxAttempts)
> {
> if (socket)
> {
> ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(socket);
> socket = nullptr;
> }
> OnConnectionFailed.Broadcast();
> connectionAttmpts = 0;
> }
> else
> {
> EstablishConnection();
> }
> }
> }, TStatId(), nullptr, ENamedThreads::GameThread);
> }
>
> void UEthernetSightswarm::CloseConnection()
> {
> isRunning = false;
> bool res = false;
>
> if (FutureThread.IsValid())
> {
> FutureThread.Wait();
> FutureThread.Get();
> }
>
>
> if (socket)
> {
> if (socket->GetConnectionState() == ESocketConnectionState::SCS_Connected)
> res = socket->Close();
>
> ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(socket);
> socket = nullptr;
> }
>
> UE_LOG(LogTemp, Warning, TEXT("closing is %s"), res ? *FString("sucssess") : *FString("unsucssess"));
> }
thank to everyone in advance.