C# - async await task freezing the main thread

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By _bjork

This is probably something regarding C#, but i’m not figuring out why. It’s my first time dealing with Tasks so I have no clue what’s wrong at all.

I’m currently working on a SceneManager class to load scenes, and the loading works fine, but I want it to work asynchronously and I don’t get why it’s hanging on the main thread (during loading it freezes, Not responding, as if it weren’t sync).

Here’s my code:

This is the loading method, loads properly.

private async Task ChangeScene(string path, SceneTree tree)
{
    ResourceInteractiveLoader ril = ResourceLoader.LoadInteractive(path);

    while (true)
    {
        Error err = ril.Poll();
        if (err == Error.FileEof)
        {
            Resource res = ril.GetResource();
            GD.Print("Loading done");
            break;
        }
        if (err == Error.Ok)
        {
            float progress = (float)ril.GetStage() / (float)ril.GetStageCount();
            GD.Print(progress);
        }

        await (ToSignal(tree, "idle_frame"));
    }
}

This is the function in the same script that runs the task.

    public static async void LoadScene(string path, SceneTree tree)
{
    await Task.Run(async () =>
    {
        await SceneManager.Instance.ChangeScene(path, tree);
    });
}

My SceneManager.cs is a C# singleton class that inherits node (to call ToSignal()), and I call my LoadScene call on my Global.cs ChangeScene function:

    public static void ChangeScene(string path)
{
    SceneManager.LoadScene(path, tree);
}

Finally the ChangeScene call is linked to a Signal when pressing a button:

public void OnStartGamePressed()
{
    Global.ChangeScene("res://Assets/Scenes/game.tscn");
}

I have no idea what’s wrong, any tips?

:bust_in_silhouette: Reply From: kelaia

Task.Run should execute the code on another thread, since you are doing this you shouldn’t use the “await ToSignal”. Just let it block until is finished. Although I’m not sure if you really need the Resource Interactive Loader since you are offloading the task to another thread.

The method described here is to load on the main thread (that’s why the code is inside de _process method), the difference is that using this method you won’t just wait until the resource is fully loaded, you can do things step by step.