question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

What is UniTaskVoid?

See original GitHub issue

So why do we need UniTaskVoid? After reading README and googling I still cannot understand its purpose. It seems like it is a UniRx replacement for async void but you still need to .Forget() it - you can do the same with UniTask. Apart from that, you can’t use it for Unity events like Start. Also, I’m using async void Start in conjuction with UniRx, are there any downsides of it?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

12reactions
OJuergencommented, Jan 13, 2020

TL;DR I think you can use private async void Start(), but calling a function that returns UniTaskVoid is better practice.

Disclaimer: not an expert, take with a grain of salt.

In principal async void Start() works. The task is scheduled and executed by the Unity main game loop. The main concern here is exception handling. Consider

private async void Start()
{
    await UniTask.Delay(1000);
    throw new Exception();
}

and compare with

private void Start()
{
    OnStart();
}

private async UniTaskVoid OnStart()
{
    await UniTask.Delay(1000);
    throw new Exception();
}

In the first case, the exception bubbles up to the Unity game loop where it is caught and logged and sent to UnityAnalytics. In the second case, it is caught by the UniTask library and logged by UniTaskScheduler where you can also configure the log level for this (warning by default). If OnStart() would return UniTask, the exception would only be logged with the next garbage collection, which happens at some undefined time in the future. Could also call Forget() on it or wrap it in UniTask.Void to prevent this.

Unity is special, because of the main game loop where all exceptions are caught. But in general, it is good practice to avoid async void, because when you kick off a task and don’t await it and it throws, the exception can get lost. And even if you were to wrap the starting of the task in a try/catch, the exception would ‘sneak out’ and crash your app. You want to make sure you know what happens with any exceptions that are thrown. I think with UniTask exceptions don’t get lost, because the tasks are executed via the Unity game loop. So async void is maybe not quite as dangerous. Since Unity has no async/await built in, we cannot avoid async void completely, anyway. With UniTaskVoid and UniTask.Void, the place where the async void actually happens is within the library code and handled there. I think it is good to avoid async void in your own code as good as you can and use UniTaskVoid instead.

3reactions
neuecccommented, Jan 10, 2020

unfortunately async void is system reserved so can not replace. for eventhandling

FooEvent += () => UniTask.Void(async () => { /* */ })

otherwise use Forget().

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cysharp/UniTask: Provides an efficient allocation ...
Provides an efficient allocation free async/await integration for Unity. Struct based UniTask<T> and custom AsyncMethodBuilder to achieve zero allocation; Makes ...
Read more >
How UniTaskVoid subscribe to an event?
async UniTaskVoid subscription?? ... I found some solution. It works fine but I do something wrong because Rider says: "Closure can be eliminated: ......
Read more >
Introduction to asynchronous programming in Unity
Executing tasks over several update calls? Let's explore different approaches to asynchronous programming in Unity game engine.
Read more >
UniTask Problem: How do you await a function?
Hello, I'm new to UniTask and I don't know how to make the async function await the task I'm calling inside it. Anyone...
Read more >
UniTask Struct
Name, Description. Action(Func<UniTaskVoid>). helper of create add UniTaskVoid to delegate. For example: FooAction = UniTask.Action(async () => { /* */ }).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found