-2

I am trying to call a async function in loop to spawn object. it doesn't work as I expected. Dictionary is giving errors about adding same item multiple times. I can't make the whole function async. Here is the code:

public Dictionary_String_Prop GeneratePlaceables(List<PropData> props, Prop parent = null)
{
    Dictionary_String_Prop temp = new Dictionary_String_Prop ();
    if(props == null)
    {
        Debugger.Log("PropdataList Empty: Returning Empty Dictionary");
        return temp;
    }
    for (int i = 0; i < props.Count; i++)
    {
        var result = GameModeGame.Get().placeableDB[props[i].dataID].Prefab;
        PropData propData = props[i];
        result.InstantiateAsync(props[i].sTransform.Position(), props[i].sTransform.Rotation()).Completed += a => 
        { 
            Placeable p = a.Result.GetComponent<Placeable>();

            p.uniqueID = propData.uniqueID;
            p.State = propData.state;
            p.InitData();
            if(parent)
                p.SetParent(parent);
            else
                p.transform.SetParent(manager.transform);

            p.transform.localScale = propData.sTransform.Scale();

            p.children = GeneratePlaceables(propData.placeables, p);

            temp.DebugLog();
            temp.Add(p.uniqueID, p);
            manager.allProps.Add(p.uniqueID, p);
        };
    }
    return temp;
}

I also tried to save all the instantiation task into an array and then use Task.WaitAll() to wait for thread to finish and then return from function but it also throws errors.

Question:- How can I instantiate every object asynchronously before exiting loop?

darpan1118
  • 99
  • 8
  • 1
    What is `Dictionary_String_Prop` ? Is it a threadsafe dictionary? (Like `ConcurrentDictionary`). What is the prototype for `InstantiateAsync` ? – Neil Feb 21 '20 at 09:25
  • It's a serialised dictionary. I am not sure about thread safe. Maybe I should test with normal dictionary. – darpan1118 Feb 21 '20 at 09:37
  • If `InstantiateAsync` is really async, then you aren't waiting for those tasks to be finished before existing the function. Does this whole function really need to be async? – Neil Feb 21 '20 at 09:40
  • It is from Unity's API. `public static AsyncOperationHandle InstantiateAsync(object key, Transform parent = null, bool instantiateInWorldSpace = false, bool trackHandle = true)` its the whole syntax I copied from there website. Here is the [link](https://docs.unity3d.com/Packages/com.unity.addressables@0.8/api/UnityEngine.AddressableAssets.Addressables.html) of the page. – darpan1118 Feb 21 '20 at 09:44

1 Answers1

1

You may want to review the documentation for async/await for c# : https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

Each async method needs a matching await in your code you are not awaiting the result of the task so....

result.InstantiateAsync(.....

Needs an await:

await result.InstantiateAsync(.....

But this has effects that you will need to make your function async:

public Dictionary_String_Prop GeneratePlaceables(List<PropData> props, Prop parent = null)

Needs changing to:

public async Task<Dictionary_String_Prop> GeneratePlaceables(List<PropData> props, Prop parent = null)

Any method calling GeneratePlaceables will also need an await: Why use Async/await all the way down


If you cna't make changes to your functions there is another method that where you can wait syncronously for th result:

Foo foo = GetFooAsync(...).GetAwaiter().GetResult();

So:

result.InstantiateAsync(....).GetAwaiter().GetResult();

This won't require the changes the the function etc...

Hope this helps

Mark Davies
  • 1,447
  • 1
  • 15
  • 30