Skip to content

Instantly share code, notes, and snippets.

@baudii
Last active November 4, 2024 23:57
Show Gist options
  • Select an option

  • Save baudii/ce23d68bc6670b2cff8ca1e73e4d63ef to your computer and use it in GitHub Desktop.

Select an option

Save baudii/ce23d68bc6670b2cff8ca1e73e4d63ef to your computer and use it in GitHub Desktop.
Simple extension method that converts Unity's AsyncOperation into a Task to use it with await. Unlike extending GetAwaiter(), this implementation supports cancellation tokens
public static Task AsTask(this AsyncOperation asyncOperation, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
if (asyncOperation == null)
throw new ArgumentNullException(nameof(asyncOperation), "Provided async operation is null");
if (asyncOperation.isDone)
return Task.CompletedTask;
var tcs = new TaskCompletionSource<object>();
IDisposable registration = null;
if (cancellationToken.CanBeCanceled)
registration = cancellationToken.Register(OnCanceled);
asyncOperation.completed += OnCompleted;
return tcs.Task;
void OnCompleted(AsyncOperation op)
{
registration?.Dispose();
asyncOperation.completed -= OnCompleted;
tcs.TrySetResult(null);
}
void OnCanceled()
{
registration.Dispose();
asyncOperation.completed -= OnCompleted;
tcs.TrySetCanceled(cancellationToken);
}
}
// Example 1:
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName);
await asyncOperation.AsTask(cancellationToken);
// Example 2:
AsyncOperation asyncOperation = Resources.LoadAsync<GameObject>(resourcePath);
await asyncOperation.AsTask();
// Example 3:
var asyncOperation = webRequest.SendWebRequest();
await asyncOperation.AsTask(timeoutMilliseconds);
// Example 4:
AssetBundleRequest asyncOperation = bundle.LoadAssetAsync<GameObject>(assetName);
await asyncOperation.AsTask();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment