У меня есть функция, которая загружает несколько ресурсов через асинхронный режим, и я хочу вызвать действие onComplete
, когда все ресурсы загружены, но в настоящее время, учитывая природу асинхронности, я не уверен, как заставить мою функцию делать это, поскольку я относительно новичок. программированию в асинхронном режиме.
public void Load(Action onComplete)
{
foreach (var kvp in _db)
{
var key = kvp.Key;
var assetRef = kvp.Value;
assetRef.LoadAssetAsync<TAsset>().Completed += handle =>
{
if (handle.Status == AsyncOperationStatus.Succeeded)
_loadedAssets.Add(key, handle.Result);
//check if all assets have been loaded and then call onComplete
};
}
}
@OlivierJacot-Descombes Но при этом onComplete будет вызываться несколько раз для каждого загруженного актива. Я пытаюсь сказать, что хочу загрузить 10 ресурсов в словарь _db, я хочу вызвать onComplete, как только все 10 будут загружены.
@WDUK - В вашем коде есть состояние гонки. assetRef.LoadAssetAsync<TAsset>()
должен завершить вызов, прежде чем вы сможете организовать событие, поэтому есть вероятность, что Completed
будет вызван до того, как это будет сделано. Я бы изменил ваш код, чтобы предотвратить это.
А нельзя чек типа if (_loadedAssets.Count == _db.Count) { onComplete(); }
?
Вам следует использовать Microsoft Reactive Framework (он же Rx) — NuGet System.Reactive
и добавить using System.Reactive.Linq;
— тогда вы сможете сделать это:
public void Load2(Action onComplete)
{
(
from kvp in _db.ToObservable()
let key = kvp.Key
let assetRef = kvp.Value
let assetLoader = assetRef.LoadAssetAsync<TAsset>()
from handle in
Observable
.FromEvent<Action<AssetHandle>, AssetHandle>(
h => assetLoader.Completed += h,
h => assetLoader.Completed -= h)
.Take(1)
where handle.Status == AsyncOperationStatus.Succeeded
select new { key, handle.Result }
)
.Subscribe(
x => _loadedAssets.Add(x.key, x.Result),
() => onComplete());
}
Теперь это должно сработать. Мне пришлось перепроектировать некоторые типы, но, думаю, я с этим справился. Состояние гонки все еще существует в вашем коде.
Все, что идет после
Completed +=
, выполняется после завершения асинхронных функций. Так что просто звонитеonComplete
, где ваш комментарий:onComplete();
илиonComplete?.Invoke();
.