I have a function that asynchronously loads a xml file, parses it, and adds certain values to a list. I'm using async and await for this. The issue I've run into is that after calling await the program moves on to executing code that accesses that list before the async function has finished adding all items.
My static class with async function:
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Xml.Linq;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.AddressableAssets;
namespace Drok.Localization
{
public static class Localization
{
/// <summary>
/// The currently available languages.
/// </summary>
public static List<string> Available { get; private set; } = new List<string>();
/// <summary>
/// The currently selected language.
/// </summary>
public static string Current { get; private set; } = null;
public static async Task Initialize()
{
await LoadMetaData();
}
private static async Task LoadMetaData()
{
AsyncOperationHandle<TextAsset> handle = Addressables.LoadAssetAsync<TextAsset>("Localization/meta.xml");
TextAsset metaDataFile = await handle.Task;
XDocument metaXMLData = XDocument.Parse(metaDataFile.text);
IEnumerable<XElement> elements = metaXMLData.Element("LangMeta").Elements();
foreach (XElement e in elements)
{
string lang = e.Attribute("lang").Value;
int id = Int32.Parse(e.Attribute("id").Value);
Debug.LogFormat("Language {0} is availible with id {1}.", lang, id);
Available.Add(lang);
}
}
public static void LoadLanguage(string lang)
{
Current = lang;
throw new NotImplementedException();
}
public static string GetString(string key)
{
return key;
}
}
}
The class that initializes it and accesses the list:
using Drok.Localization;
using UnityEngine;
namespace Spellbound.Menu
{
public class LanguageMenu : MonoBehaviour
{
private async void Awake()
{
await Localization.Initialize();
}
private void Start()
{
Debug.Log(Localization.Available.Count);
}
private void Update()
{
}
}
}
I have no idea how to prevent access to that list until after all items have been added. The code I posted just collects info on what languages are available so that only the one language being used can be loaded later.
A Task<T> represents some value (of type T) that will be determined in the future. If you make your property this type, then it will force all callers to await for it to be loaded:
public static class Localization
{
public static Task<List<string>> Available { get; private set; }
static Localization() => Available = LoadMetaDataAsync();
private static async Task<List<string>> LoadMetaDataAsync()
{
var results = new List<string>();
...
results.Add(lang);
return results;
}
}
Usage:
private async Task StartAsync()
{
var languages = await Localization.Available;
Debug.Log(languages.Available.Count);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With