SlideShare a Scribd company logo
1 of 61
Download to read offline
Yoshifumi Kawai / @neuecc
https://github.com/Cysharp/MagicOnion
C#
Rx vs Async/Await
Can Rx be used with asynchronous operations?
IObservable<T> time
event
async
IE<T>
A structure which treats asynchronous as synchronous
static string GetSync(int page)
{
try
{
var url = "http://...?page=" + page;
var html = GetHttpStringSync(url);
return html;
}
catch
{
return "Error";
}
}
static async Task<string> GetAsync(int page)
{
try
{
var url = "http://...?page=" + page;
var html = await GetHttpStringAsync(url);
return html;
}
catch
{
return "Error";
}
}
Synchronous Asynchronous
Single(1)Multiple(*)
var x = f(); var x = await f();
var query = from person in sequence
where person.Age >= 20
select person.Name;
foreach (var item in query)
{
OnNext(item);
}
var query = from person in sequence
where person.Age >= 20
select person.Name;
query.Subscribe(item =>
{
OnNext(item);
});
IEnumerble<T> IObservable<T>
T Task<T>
The ability to display everything with IObservable<T>
It actually isn’t suitable for complex control
It actually isn’t suitable for complex control
Async/await for asynchronous, Rx for event
What is aysnc/await?
async/await: Multithread…
it is not!!!
Asynchronous is not multithread
This must be persistently said over and over again.
It is only correct that there are also times when it becomes multithread.
Coroutines aren’t multithread, are they?
JavaScript isn’t multithread, is it?
But task is multithread, right?
Yes and no.
Task is something that was originally multithread, and, since that is what
is being recycled, there are often cases in which it is behaviorally
multithread, making it easy for misunderstandings to form.
Absolutely Not
Around when async/await was being implemented in C# 5.0(.NET 4.5),
it was faster to recycle the already-existing structure (.NET 4.0 Task).
There are things that aren’t known until something is widely used.
There are also consequences and liabilities
In investigation of the asynchronous model of Midori (Microsoft’s
managed OS project using C# style language), in regard to Task, the
performance side (in making something severe like an OS) was especially
a let down.
http://joeduffyblog.com/2015/11/19/asynchronous-everything/
For C# as it is now, that’s being repaid with the unique evolution of
ValueTask.
Absolutely Not
Around when async/await was being implemented in C# 5.0(.NET 4.5),
it was faster to recycle the already-existing structure (.NET 4.0 Task).
There are things that aren’t known until something is widely used.
There are also consequences and liabilities
In investigation of the asynchronous model of Midori (Microsoft’s
managed OS project using C# style language), in regard to Task, the
performance side (in making something severe like an OS) was especially
a let down.
http://joeduffyblog.com/2015/11/19/asynchronous-everything/
For C# as it is now, that’s being repaid with the unique evolution of
ValueTask.
How async/await Works
async Task<string> SampleTextLoadAsync()
{
Debug.Log("Before LoadAsync:" +Time.frameCount); // frame:1
var textAsset = await Resources.LoadAsync<TextAsset>("te") as TextAsset;
Debug.Log("After LoadAsync:" +Time.frameCount); // frame:2
return textAsset.text;
}
Manual procedures -> automation
A callback chain is automatically created and run using await.
Since it also does things such as exception creation and optimization,
there are also instances in which the efficiency is better than when
using manual procedures.
Is async/await a coroutine?
The essential meaning is CPS conversion with implementation
details as a state machine.
Since a coroutine is only chosen as an implementation for
optimization, even if it enters into it, that’s not what it means.
Asynchronous is not asynchronous
Async transmits to a higher level (the method of calling async becomes async).
As a result, there are often instances in which it may be async, but the content
is synchronous.
Each time a continuation is called (call via a delegate) that way, there is
delegate garbage production + a calling cost, so it isn’t good.
public class MyAwaiter<T> : INotifyCompletion
{
bool IsCompleted { get; }
T GetResult();
void OnCompleted(Action continuation);
}
// var result = await foo; ends up as follows.
if (awaiter.IsCompleted)
{
// If there is an exception, it is thrown again with GetResult.
var result = awaiter.GetResult();
// ...the beginning of await is executed.
}
else
{
// Registration of a continuation (Actually, since it is optimized, the lambda expression isn't used every time).
awaiter.OnCompleted(() =>
{
// If there is an exception, it is rethrown with GetResult.
var result = awaiter.GetResult();
// ...the beginning of await is executed.
});
return;
}
Not all continuations are created
public async Task FooBarBazAsync()
{
await Task.Yield();
Console.WriteLine("foo");
await Task.Yield();
Console.WriteLine(“bar");
await Task.Yield();
Console.WriteLine("baz");
}
Not all continuations are created
public async Task FooBarBazAsync()
{
await Task.Yield();
Console.WriteLine("foo");
await Task.Yield();
Console.WriteLine(“bar");
await Task.Yield();
Console.WriteLine("baz");
}
Why UniTask?
UniRx.Async’s main class
https://github.com/Cysharp/UniTask
It has been possible to implement async return values other than Task since C# 7.0.
It is Task (ValueTask equivalent) structured with the unique form compatible with
async used in that.
In other words, a personalized asynchronous framework.
C# 7.0 can be used after Unity 2018.3.
Why is it needed?
By replacing everything, the liabilities of Task itself are completely ignored.
Since Unity itself is a special execution environment, it has the fastest implementation
through specialization.
Unity is (in general) single thread
C++ engine layer + C# scripting layer.
Handling on the C# side is nearly all single thread.
(Coroutines, WWW, AsyncOperation, etc…)
When async/await is neglected due to Task, it is immediately
transferred to a thread pool.
-> Delay, ContinueWith, Run, etc…
Async/await(Task) has a multithread -> single thread unification
function, but, if it was single thread to begin with, wouldn’t deleting
that unification layer increase both performance and ease of
handling?
XxxContext is the overhead of Task
Two varieties of capture, ExecutionContext and SynchronizationContext
XxxContext is the overhead of Task
Two varieties of capture, ExecutionContext and SynchronizationContext
Utilities for coroutine replacement
UniTask.Delay
UniTask.WaitUntil
UniTask.WaitWhile
UniTask.WaitUntilValueChanged
UniTask.Run
UniTask.Yield
UniTask.SwitchToMainThread
UniTask.SwitchToThreadPool
await AsyncOperation
IEnumerator FooCoroutine(Func<int> resultCallback, Func<Exception> exceptionCallback)
{
int x = 0;
Exception error = null;
yield return Nanikamatu(v => x = v, ex => error = ex);
if (error == null)
{
resultCallback(x);
}
else
{
exceptionCallback(error);
}
}
UniTask<int> FooAsync()
{
var x = await NanikasuruAsync();
return x;
}
IEnumerator FooCoroutine(Func<int> resultCallback, Func<Exception> exceptionCallback)
{
int x = 0;
Exception error = null;
yield return Nanikamatu(v => x = v, ex => error = ex);
if (error == null)
{
resultCallback(x);
}
else
{
exceptionCallback(error);
}
}
UniTask<int> FooAsync()
{
var x = await NanikasuruAsync();
return x;
}
UniTask + async/await for performance
Since UniTask is specialized for Unity, it has far greater performance than Task.
No ExecutionContext, No SynchronizationContext
UniTask has less allocation than coroutine implementation.
It has greater performance in asynchronous sections than UniRx(Observable).
UniTask + async/await for ease of use
Since single thread is assumed, there are no multithread traps.
It offers an abundance of functions and has the ability to practically replace
coroutines.
UniTask leaks can be easily avoided with UniTask Tracker.
There’s also no problem in using it in combination with Task and Rx.
UniTask + async/await for performance
Since UniTask is specialized for Unity, it has far greater performance than Task.
No ExecutionContext, No SynchronizationContext
UniTask has less allocation than coroutine implementation.
It has greater performance in asynchronous sections than UniRx(Observable).
UniTask + async/await for ease of use
Since single thread is assumed, there are no multithread traps.
It offers an abundance of functions and has the ability to practically replace
coroutines.
UniTask leaks can be easily avoided with UniTask Tracker.
There’s also no problem in using it in combination with Task and Rx.
The States of UniTask
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
return 10;
}
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
return 10;
}
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
return 10;
}
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
throw new System.Exception("Error");
}
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
throw new System.Exception("Error");
}
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
throw new OperationCanceledException();
}
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
throw new OperationCanceledException();
}
public async UniTask<int> BarAsync()
{
var x = await FooAsync();
return x * 2;
}
public void Baz()
{
BarAsync().Forget();
}
public async UniTask<int> FooAsync()
{
await UniTask.Yield();
throw new OperationCanceledException();
}
public async UniTask<int> BarAsync()
{
var x = await FooAsync();
return x * 2;
}
public void Baz()
{
BarAsync().Forget();
}
public async UniTask<int> BarAsync()
{
try
{
var x = await FooAsync();
return x * 2;
}
catch (Exception ex) when (!(ex is OperationCanceledException))
{
return -1;
}
}
public async UniTask<int> BarAsync()
{
try
{
var x = await FooAsync();
return x * 2;
}
catch (Exception ex) when (!(ex is OperationCanceledException))
{
// Since it seems to be an unrecoverable exception, do something along the lines of Open Dialog and Return to Title.
DialogService.ShowReturnToTitleAsync().Forget(); // Handled like fire and forget.
// Everything in the original call is tossed and terminated using a cancel chain.
throw new OperationCanceledException();
}
}
Cancellation of Async
Cancellation is troublesome
If only Rx could knock out IDisposable return values with one punch!
(Instead, there is no IDisposable allocation in async/await.)
Instead, as an argument (CancellationToken is passed around).
public Task<int> FooAsync(int x, int y, CancellationToken cancellationToken = default)
{
var x = await BarAsync(x, y, cancellationToken);
return x;
}
Cancel = OperationCanceledException
There is no need for user code to check cancellationToken.IsCancelationRequested.
That’s because the user code section is synchronous.
OperationCanceledException is thrown from an asynchronous source
= asyncOperation.ConfigureAwait(token), UniTask.Delay(token), etc…
At any rate, pass, that should be enough.
Since an asynchronous source should be processing it, reporting that much should be OK.
Oh, but that’s so much trouble!!!
There’s no way to hack it to get it to do it automatically (without dropping performance).
MonoBehaviour/OnDestroy is convenient for Unity
public class FooBehaviour : MonoBehaviour
{
CancellationTokenSource cts;
void Start()
{
cts = new CancellationTokenSource();
}
void OnDestroy()
{
cts.Cancel();
cts.Dispose();
}
}
Is there a high cost?
Yes!
If Cancel is a kind of exception and only goes off occasionally, it shouldn’t be
much of a problem, but when Cancel turns normal and becomes assumed,
depending on the circumstances, it can turn into something pretty harsh.
For instance, what if an exception goes off with the cancel of 10,000 Cubes that
are on screen at time of a scene transition linked to a MonoBehaviour scene…?
UniTask.SuppressCancellationThrow
In UniTask, there is SuppressCancellationThrow, which converts cancel into
(bool isCanceled, T value).
However, be careful since only an asynchronous source can control an
exception.
Async Event Handling
Events can be implemented with async/await
await button.OnClickAsync();
await gameObject.OnCollisionEnterAsync();
There are implementations for these in UniTask.
async UniTask TripleClick(CancellationToken token)
{
await button.OnClickAsync(token);
await button.OnClickAsync(token);
await button.OnClickAsync(token);
Debug.Log("Three times clicked");
}
Events can be implemented with async/await
await button.OnClickAsync();
await gameObject.OnCollisionEnterAsync();
There are implementations for these in UniTask.
async UniTask TripleClick(CancellationToken token)
{
// Acquiring a Handler at the start is more efficient than doing OnClick/token passing each time.
using (var handler = button.GetAsyncClickEventHandler(token))
{
await handler.OnClickAsync();
await handler.OnClickAsync();
await handler.OnClickAsync();
Debug.Log("Three times clicked");
}
Well, it may be a little unreasonable.
Rx is generally better for event handing.
The code becomes longer and items to consider on the performance
side increase quite a bit.
However, when implementing complex flow, it’s possible to write in a
more clear and straightforward manner with “code awaiting a
synchronous event” than by making do with an Rx operator.
It’s not bad to have this kind of technique in your wallet, is it?
(In the same way, await is also possible with ReactiveProperty.)
Reusable Promise
For the sake of performance
Reuse is possible with local variables (only for part of an asynchronous source).
async UniTask DelayFiveAsync1()
{
for (int i = 0; i < 5; i++)
{
// Delay is created each time.
await UniTask.Delay(i * 1000);
Debug.Log(i);
}
}
[[[async UniTask DelayFiveAsync2()
{
// Delay is recycled.
var delay = UniTask.Delay(i * 1000);
for (int i = 0; i < 5; i++)
{
await delay;
Debug.Log(i);
}
}]]]
Conclusion
Don’t be afraid!
Performance is not a problem (when UniTask is used).
Practice has already been established (when UniTask is used).
There’s almost no damage from overdoing things (strongly speaking, asynchronous
pollution).
It’s at a level at which there’s no reason not to go for it, so GO right now.
Recommended to use with UniRx.Async
async/await has been redesigned for Unity with performance and user-friendliness.
Everything used in Unity has been made capable of await.
Don’t be afraid of normal Task not being used!
Let’s traverse the leading edge, surpassing all language and the ordinary .NET!

More Related Content

What's hot

What's hot (20)

【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
 
UniRx完全に理解した
UniRx完全に理解したUniRx完全に理解した
UniRx完全に理解した
 
【Unity道場スペシャル 2017札幌】最適化をする前に覚えておきたい技術 -札幌編-
【Unity道場スペシャル 2017札幌】最適化をする前に覚えておきたい技術 -札幌編-【Unity道場スペシャル 2017札幌】最適化をする前に覚えておきたい技術 -札幌編-
【Unity道場スペシャル 2017札幌】最適化をする前に覚えておきたい技術 -札幌編-
 
Unityではじめるオープンワールド制作 エンジニア編
Unityではじめるオープンワールド制作 エンジニア編Unityではじめるオープンワールド制作 エンジニア編
Unityではじめるオープンワールド制作 エンジニア編
 
Unity Internals: Memory and Performance
Unity Internals: Memory and PerformanceUnity Internals: Memory and Performance
Unity Internals: Memory and Performance
 
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
 
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
 
【CEDEC2018】Scriptable Render Pipelineを使ってみよう
【CEDEC2018】Scriptable Render Pipelineを使ってみよう【CEDEC2018】Scriptable Render Pipelineを使ってみよう
【CEDEC2018】Scriptable Render Pipelineを使ってみよう
 
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
 
【Unity道場スペシャル 2017博多】クォータニオン完全マスター
【Unity道場スペシャル 2017博多】クォータニオン完全マスター【Unity道場スペシャル 2017博多】クォータニオン完全マスター
【Unity道場スペシャル 2017博多】クォータニオン完全マスター
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動についてUE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
 
50分でわかるブループリントについて
50分でわかるブループリントについて50分でわかるブループリントについて
50分でわかるブループリントについて
 
60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編
 
【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~
【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~
【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~
 
Unreal Studioのご紹介
Unreal Studioのご紹介Unreal Studioのご紹介
Unreal Studioのご紹介
 
레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다
 
UE4のモバイル開発におけるコンテンツアップデートの話 - Chunk IDとの激闘編 -
UE4のモバイル開発におけるコンテンツアップデートの話 - Chunk IDとの激闘編 -UE4のモバイル開発におけるコンテンツアップデートの話 - Chunk IDとの激闘編 -
UE4のモバイル開発におけるコンテンツアップデートの話 - Chunk IDとの激闘編 -
 
UnityのクラッシュをBacktraceでデバッグしよう!
UnityのクラッシュをBacktraceでデバッグしよう!UnityのクラッシュをBacktraceでデバッグしよう!
UnityのクラッシュをBacktraceでデバッグしよう!
 
UnityのMultiplayサービスの得意な事
UnityのMultiplayサービスの得意な事UnityのMultiplayサービスの得意な事
UnityのMultiplayサービスの得意な事
 

Similar to Deep Dive async/await in Unity with UniTask(EN)

Asynchronous in dot net4
Asynchronous in dot net4Asynchronous in dot net4
Asynchronous in dot net4
Wei Sun
 
Asynchronous programming in .net 4.5 with c#
Asynchronous programming in .net 4.5 with c#Asynchronous programming in .net 4.5 with c#
Asynchronous programming in .net 4.5 with c#
Binu Bhasuran
 
Using Async in your Mobile Apps - Marek Safar
Using Async in your Mobile Apps - Marek SafarUsing Async in your Mobile Apps - Marek Safar
Using Async in your Mobile Apps - Marek Safar
Xamarin
 
CTU June 2011 - C# 5.0 - ASYNC & Await
CTU June 2011 - C# 5.0 - ASYNC & AwaitCTU June 2011 - C# 5.0 - ASYNC & Await
CTU June 2011 - C# 5.0 - ASYNC & Await
Spiffy
 

Similar to Deep Dive async/await in Unity with UniTask(EN) (20)

20220529_UniTask_Intro.pptx
20220529_UniTask_Intro.pptx20220529_UniTask_Intro.pptx
20220529_UniTask_Intro.pptx
 
Async Programming in C# 5
Async Programming in C# 5Async Programming in C# 5
Async Programming in C# 5
 
Asynchronous development in JavaScript
Asynchronous development  in JavaScriptAsynchronous development  in JavaScript
Asynchronous development in JavaScript
 
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel ZikmundNDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
 
Leveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results AsynchrhonouslyLeveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results Asynchrhonously
 
Sync with async
Sync with  asyncSync with  async
Sync with async
 
Asynchronous in dot net4
Asynchronous in dot net4Asynchronous in dot net4
Asynchronous in dot net4
 
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and python
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
Asynchronous programming in .net 4.5 with c#
Asynchronous programming in .net 4.5 with c#Asynchronous programming in .net 4.5 with c#
Asynchronous programming in .net 4.5 with c#
 
Node.js: CAMTA Presentation
Node.js: CAMTA PresentationNode.js: CAMTA Presentation
Node.js: CAMTA Presentation
 
Using Async in your Mobile Apps - Marek Safar
Using Async in your Mobile Apps - Marek SafarUsing Async in your Mobile Apps - Marek Safar
Using Async in your Mobile Apps - Marek Safar
 
Leverage CompletableFutures to handle async queries. DevNexus 2022
Leverage CompletableFutures to handle async queries. DevNexus 2022Leverage CompletableFutures to handle async queries. DevNexus 2022
Leverage CompletableFutures to handle async queries. DevNexus 2022
 
4Developers 2015: Programowanie synchroniczne i asynchroniczne - dwa światy k...
4Developers 2015: Programowanie synchroniczne i asynchroniczne - dwa światy k...4Developers 2015: Programowanie synchroniczne i asynchroniczne - dwa światy k...
4Developers 2015: Programowanie synchroniczne i asynchroniczne - dwa światy k...
 
Asynchronní programování
Asynchronní programováníAsynchronní programování
Asynchronní programování
 
CTU June 2011 - C# 5.0 - ASYNC & Await
CTU June 2011 - C# 5.0 - ASYNC & AwaitCTU June 2011 - C# 5.0 - ASYNC & Await
CTU June 2011 - C# 5.0 - ASYNC & Await
 
Ddd melbourne 2011 C# async ctp
Ddd melbourne 2011  C# async ctpDdd melbourne 2011  C# async ctp
Ddd melbourne 2011 C# async ctp
 
Task parallel library presentation
Task parallel library presentationTask parallel library presentation
Task parallel library presentation
 

More from Yoshifumi Kawai

ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
Yoshifumi Kawai
 
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニーUnity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
Yoshifumi Kawai
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
Yoshifumi Kawai
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
Yoshifumi Kawai
 
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Yoshifumi Kawai
 

More from Yoshifumi Kawai (20)

A quick tour of the Cysharp OSS
A quick tour of the Cysharp OSSA quick tour of the Cysharp OSS
A quick tour of the Cysharp OSS
 
Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#
 
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
 
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
 
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニーUnity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
 
Implements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNetImplements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNet
 
The Usage and Patterns of MagicOnion
The Usage and Patterns of MagicOnionThe Usage and Patterns of MagicOnion
The Usage and Patterns of MagicOnion
 
True Cloud Native Batch Workflow for .NET with MicroBatchFramework
True Cloud Native Batch Workflow for .NET with MicroBatchFrameworkTrue Cloud Native Batch Workflow for .NET with MicroBatchFramework
True Cloud Native Batch Workflow for .NET with MicroBatchFramework
 
Binary Reading in C#
Binary Reading in C#Binary Reading in C#
Binary Reading in C#
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
 
RuntimeUnitTestToolkit for Unity(English)
RuntimeUnitTestToolkit for Unity(English)RuntimeUnitTestToolkit for Unity(English)
RuntimeUnitTestToolkit for Unity(English)
 
RuntimeUnitTestToolkit for Unity
RuntimeUnitTestToolkit for UnityRuntimeUnitTestToolkit for Unity
RuntimeUnitTestToolkit for Unity
 
NextGen Server/Client Architecture - gRPC + Unity + C#
NextGen Server/Client Architecture - gRPC + Unity + C#NextGen Server/Client Architecture - gRPC + Unity + C#
NextGen Server/Client Architecture - gRPC + Unity + C#
 
How to make the Fastest C# Serializer, In the case of ZeroFormatter
How to make the Fastest C# Serializer, In the case of ZeroFormatterHow to make the Fastest C# Serializer, In the case of ZeroFormatter
How to make the Fastest C# Serializer, In the case of ZeroFormatter
 
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
 
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPCZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
 
Photon Server Deep Dive - View from Implmentation of PhotonWire, Multiplayer ...
Photon Server Deep Dive - View from Implmentation of PhotonWire, Multiplayer ...Photon Server Deep Dive - View from Implmentation of PhotonWire, Multiplayer ...
Photon Server Deep Dive - View from Implmentation of PhotonWire, Multiplayer ...
 
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
 
Clash of Oni Online - VR Multiplay Sword Action
Clash of Oni Online - VR Multiplay Sword Action Clash of Oni Online - VR Multiplay Sword Action
Clash of Oni Online - VR Multiplay Sword Action
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Recently uploaded (20)

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 

Deep Dive async/await in Unity with UniTask(EN)

  • 1.
  • 2. Yoshifumi Kawai / @neuecc https://github.com/Cysharp/MagicOnion C#
  • 4. Can Rx be used with asynchronous operations? IObservable<T> time event async IE<T>
  • 5. A structure which treats asynchronous as synchronous static string GetSync(int page) { try { var url = "http://...?page=" + page; var html = GetHttpStringSync(url); return html; } catch { return "Error"; } } static async Task<string> GetAsync(int page) { try { var url = "http://...?page=" + page; var html = await GetHttpStringAsync(url); return html; } catch { return "Error"; } }
  • 6. Synchronous Asynchronous Single(1)Multiple(*) var x = f(); var x = await f(); var query = from person in sequence where person.Age >= 20 select person.Name; foreach (var item in query) { OnNext(item); } var query = from person in sequence where person.Age >= 20 select person.Name; query.Subscribe(item => { OnNext(item); }); IEnumerble<T> IObservable<T> T Task<T>
  • 7. The ability to display everything with IObservable<T>
  • 8. It actually isn’t suitable for complex control
  • 9. It actually isn’t suitable for complex control
  • 13. Asynchronous is not multithread This must be persistently said over and over again. It is only correct that there are also times when it becomes multithread. Coroutines aren’t multithread, are they? JavaScript isn’t multithread, is it? But task is multithread, right? Yes and no. Task is something that was originally multithread, and, since that is what is being recycled, there are often cases in which it is behaviorally multithread, making it easy for misunderstandings to form.
  • 14.
  • 15.
  • 16. Absolutely Not Around when async/await was being implemented in C# 5.0(.NET 4.5), it was faster to recycle the already-existing structure (.NET 4.0 Task). There are things that aren’t known until something is widely used. There are also consequences and liabilities In investigation of the asynchronous model of Midori (Microsoft’s managed OS project using C# style language), in regard to Task, the performance side (in making something severe like an OS) was especially a let down. http://joeduffyblog.com/2015/11/19/asynchronous-everything/ For C# as it is now, that’s being repaid with the unique evolution of ValueTask.
  • 17. Absolutely Not Around when async/await was being implemented in C# 5.0(.NET 4.5), it was faster to recycle the already-existing structure (.NET 4.0 Task). There are things that aren’t known until something is widely used. There are also consequences and liabilities In investigation of the asynchronous model of Midori (Microsoft’s managed OS project using C# style language), in regard to Task, the performance side (in making something severe like an OS) was especially a let down. http://joeduffyblog.com/2015/11/19/asynchronous-everything/ For C# as it is now, that’s being repaid with the unique evolution of ValueTask.
  • 19. async Task<string> SampleTextLoadAsync() { Debug.Log("Before LoadAsync:" +Time.frameCount); // frame:1 var textAsset = await Resources.LoadAsync<TextAsset>("te") as TextAsset; Debug.Log("After LoadAsync:" +Time.frameCount); // frame:2 return textAsset.text; }
  • 20. Manual procedures -> automation A callback chain is automatically created and run using await. Since it also does things such as exception creation and optimization, there are also instances in which the efficiency is better than when using manual procedures. Is async/await a coroutine? The essential meaning is CPS conversion with implementation details as a state machine. Since a coroutine is only chosen as an implementation for optimization, even if it enters into it, that’s not what it means.
  • 21. Asynchronous is not asynchronous Async transmits to a higher level (the method of calling async becomes async). As a result, there are often instances in which it may be async, but the content is synchronous. Each time a continuation is called (call via a delegate) that way, there is delegate garbage production + a calling cost, so it isn’t good.
  • 22. public class MyAwaiter<T> : INotifyCompletion { bool IsCompleted { get; } T GetResult(); void OnCompleted(Action continuation); }
  • 23. // var result = await foo; ends up as follows. if (awaiter.IsCompleted) { // If there is an exception, it is thrown again with GetResult. var result = awaiter.GetResult(); // ...the beginning of await is executed. } else { // Registration of a continuation (Actually, since it is optimized, the lambda expression isn't used every time). awaiter.OnCompleted(() => { // If there is an exception, it is rethrown with GetResult. var result = awaiter.GetResult(); // ...the beginning of await is executed. }); return; }
  • 24. Not all continuations are created public async Task FooBarBazAsync() { await Task.Yield(); Console.WriteLine("foo"); await Task.Yield(); Console.WriteLine(“bar"); await Task.Yield(); Console.WriteLine("baz"); }
  • 25. Not all continuations are created public async Task FooBarBazAsync() { await Task.Yield(); Console.WriteLine("foo"); await Task.Yield(); Console.WriteLine(“bar"); await Task.Yield(); Console.WriteLine("baz"); }
  • 27. UniRx.Async’s main class https://github.com/Cysharp/UniTask It has been possible to implement async return values other than Task since C# 7.0. It is Task (ValueTask equivalent) structured with the unique form compatible with async used in that. In other words, a personalized asynchronous framework. C# 7.0 can be used after Unity 2018.3. Why is it needed? By replacing everything, the liabilities of Task itself are completely ignored. Since Unity itself is a special execution environment, it has the fastest implementation through specialization.
  • 28. Unity is (in general) single thread C++ engine layer + C# scripting layer. Handling on the C# side is nearly all single thread. (Coroutines, WWW, AsyncOperation, etc…) When async/await is neglected due to Task, it is immediately transferred to a thread pool. -> Delay, ContinueWith, Run, etc… Async/await(Task) has a multithread -> single thread unification function, but, if it was single thread to begin with, wouldn’t deleting that unification layer increase both performance and ease of handling?
  • 29. XxxContext is the overhead of Task Two varieties of capture, ExecutionContext and SynchronizationContext
  • 30. XxxContext is the overhead of Task Two varieties of capture, ExecutionContext and SynchronizationContext
  • 31. Utilities for coroutine replacement UniTask.Delay UniTask.WaitUntil UniTask.WaitWhile UniTask.WaitUntilValueChanged UniTask.Run UniTask.Yield UniTask.SwitchToMainThread UniTask.SwitchToThreadPool await AsyncOperation
  • 32. IEnumerator FooCoroutine(Func<int> resultCallback, Func<Exception> exceptionCallback) { int x = 0; Exception error = null; yield return Nanikamatu(v => x = v, ex => error = ex); if (error == null) { resultCallback(x); } else { exceptionCallback(error); } } UniTask<int> FooAsync() { var x = await NanikasuruAsync(); return x; }
  • 33. IEnumerator FooCoroutine(Func<int> resultCallback, Func<Exception> exceptionCallback) { int x = 0; Exception error = null; yield return Nanikamatu(v => x = v, ex => error = ex); if (error == null) { resultCallback(x); } else { exceptionCallback(error); } } UniTask<int> FooAsync() { var x = await NanikasuruAsync(); return x; }
  • 34.
  • 35. UniTask + async/await for performance Since UniTask is specialized for Unity, it has far greater performance than Task. No ExecutionContext, No SynchronizationContext UniTask has less allocation than coroutine implementation. It has greater performance in asynchronous sections than UniRx(Observable). UniTask + async/await for ease of use Since single thread is assumed, there are no multithread traps. It offers an abundance of functions and has the ability to practically replace coroutines. UniTask leaks can be easily avoided with UniTask Tracker. There’s also no problem in using it in combination with Task and Rx.
  • 36. UniTask + async/await for performance Since UniTask is specialized for Unity, it has far greater performance than Task. No ExecutionContext, No SynchronizationContext UniTask has less allocation than coroutine implementation. It has greater performance in asynchronous sections than UniRx(Observable). UniTask + async/await for ease of use Since single thread is assumed, there are no multithread traps. It offers an abundance of functions and has the ability to practically replace coroutines. UniTask leaks can be easily avoided with UniTask Tracker. There’s also no problem in using it in combination with Task and Rx.
  • 37. The States of UniTask
  • 38. public enum AwaiterStatus { /// <summary>The operation has not yet completed.</summary> Pending = 0, /// <summary>The operation completed successfully.</summary> Succeeded = 1, /// <summary>The operation completed with an error.</summary> Faulted = 2, /// <summary>The operation completed due to cancellation.</summary> Canceled = 3 }
  • 39. public async UniTask<int> FooAsync() { await UniTask.Yield(); return 10; } public enum AwaiterStatus { /// <summary>The operation has not yet completed.</summary> Pending = 0, /// <summary>The operation completed successfully.</summary> Succeeded = 1, /// <summary>The operation completed with an error.</summary> Faulted = 2, /// <summary>The operation completed due to cancellation.</summary> Canceled = 3 }
  • 40. public async UniTask<int> FooAsync() { await UniTask.Yield(); return 10; } public enum AwaiterStatus { /// <summary>The operation has not yet completed.</summary> Pending = 0, /// <summary>The operation completed successfully.</summary> Succeeded = 1, /// <summary>The operation completed with an error.</summary> Faulted = 2, /// <summary>The operation completed due to cancellation.</summary> Canceled = 3 }
  • 41. public async UniTask<int> FooAsync() { await UniTask.Yield(); return 10; } public enum AwaiterStatus { /// <summary>The operation has not yet completed.</summary> Pending = 0, /// <summary>The operation completed successfully.</summary> Succeeded = 1, /// <summary>The operation completed with an error.</summary> Faulted = 2, /// <summary>The operation completed due to cancellation.</summary> Canceled = 3 }
  • 42. public async UniTask<int> FooAsync() { await UniTask.Yield(); throw new System.Exception("Error"); } public enum AwaiterStatus { /// <summary>The operation has not yet completed.</summary> Pending = 0, /// <summary>The operation completed successfully.</summary> Succeeded = 1, /// <summary>The operation completed with an error.</summary> Faulted = 2, /// <summary>The operation completed due to cancellation.</summary> Canceled = 3 }
  • 43. public async UniTask<int> FooAsync() { await UniTask.Yield(); throw new System.Exception("Error"); } public enum AwaiterStatus { /// <summary>The operation has not yet completed.</summary> Pending = 0, /// <summary>The operation completed successfully.</summary> Succeeded = 1, /// <summary>The operation completed with an error.</summary> Faulted = 2, /// <summary>The operation completed due to cancellation.</summary> Canceled = 3 }
  • 44. public async UniTask<int> FooAsync() { await UniTask.Yield(); throw new OperationCanceledException(); } public enum AwaiterStatus { /// <summary>The operation has not yet completed.</summary> Pending = 0, /// <summary>The operation completed successfully.</summary> Succeeded = 1, /// <summary>The operation completed with an error.</summary> Faulted = 2, /// <summary>The operation completed due to cancellation.</summary> Canceled = 3 }
  • 45. public async UniTask<int> FooAsync() { await UniTask.Yield(); throw new OperationCanceledException(); } public async UniTask<int> BarAsync() { var x = await FooAsync(); return x * 2; } public void Baz() { BarAsync().Forget(); }
  • 46. public async UniTask<int> FooAsync() { await UniTask.Yield(); throw new OperationCanceledException(); } public async UniTask<int> BarAsync() { var x = await FooAsync(); return x * 2; } public void Baz() { BarAsync().Forget(); }
  • 47. public async UniTask<int> BarAsync() { try { var x = await FooAsync(); return x * 2; } catch (Exception ex) when (!(ex is OperationCanceledException)) { return -1; } }
  • 48. public async UniTask<int> BarAsync() { try { var x = await FooAsync(); return x * 2; } catch (Exception ex) when (!(ex is OperationCanceledException)) { // Since it seems to be an unrecoverable exception, do something along the lines of Open Dialog and Return to Title. DialogService.ShowReturnToTitleAsync().Forget(); // Handled like fire and forget. // Everything in the original call is tossed and terminated using a cancel chain. throw new OperationCanceledException(); } }
  • 50. Cancellation is troublesome If only Rx could knock out IDisposable return values with one punch! (Instead, there is no IDisposable allocation in async/await.) Instead, as an argument (CancellationToken is passed around). public Task<int> FooAsync(int x, int y, CancellationToken cancellationToken = default) { var x = await BarAsync(x, y, cancellationToken); return x; }
  • 51. Cancel = OperationCanceledException There is no need for user code to check cancellationToken.IsCancelationRequested. That’s because the user code section is synchronous. OperationCanceledException is thrown from an asynchronous source = asyncOperation.ConfigureAwait(token), UniTask.Delay(token), etc… At any rate, pass, that should be enough. Since an asynchronous source should be processing it, reporting that much should be OK. Oh, but that’s so much trouble!!! There’s no way to hack it to get it to do it automatically (without dropping performance).
  • 52. MonoBehaviour/OnDestroy is convenient for Unity public class FooBehaviour : MonoBehaviour { CancellationTokenSource cts; void Start() { cts = new CancellationTokenSource(); } void OnDestroy() { cts.Cancel(); cts.Dispose(); } }
  • 53. Is there a high cost? Yes! If Cancel is a kind of exception and only goes off occasionally, it shouldn’t be much of a problem, but when Cancel turns normal and becomes assumed, depending on the circumstances, it can turn into something pretty harsh. For instance, what if an exception goes off with the cancel of 10,000 Cubes that are on screen at time of a scene transition linked to a MonoBehaviour scene…? UniTask.SuppressCancellationThrow In UniTask, there is SuppressCancellationThrow, which converts cancel into (bool isCanceled, T value). However, be careful since only an asynchronous source can control an exception.
  • 55. Events can be implemented with async/await await button.OnClickAsync(); await gameObject.OnCollisionEnterAsync(); There are implementations for these in UniTask. async UniTask TripleClick(CancellationToken token) { await button.OnClickAsync(token); await button.OnClickAsync(token); await button.OnClickAsync(token); Debug.Log("Three times clicked"); }
  • 56. Events can be implemented with async/await await button.OnClickAsync(); await gameObject.OnCollisionEnterAsync(); There are implementations for these in UniTask. async UniTask TripleClick(CancellationToken token) { // Acquiring a Handler at the start is more efficient than doing OnClick/token passing each time. using (var handler = button.GetAsyncClickEventHandler(token)) { await handler.OnClickAsync(); await handler.OnClickAsync(); await handler.OnClickAsync(); Debug.Log("Three times clicked"); }
  • 57. Well, it may be a little unreasonable. Rx is generally better for event handing. The code becomes longer and items to consider on the performance side increase quite a bit. However, when implementing complex flow, it’s possible to write in a more clear and straightforward manner with “code awaiting a synchronous event” than by making do with an Rx operator. It’s not bad to have this kind of technique in your wallet, is it? (In the same way, await is also possible with ReactiveProperty.)
  • 59. For the sake of performance Reuse is possible with local variables (only for part of an asynchronous source). async UniTask DelayFiveAsync1() { for (int i = 0; i < 5; i++) { // Delay is created each time. await UniTask.Delay(i * 1000); Debug.Log(i); } } [[[async UniTask DelayFiveAsync2() { // Delay is recycled. var delay = UniTask.Delay(i * 1000); for (int i = 0; i < 5; i++) { await delay; Debug.Log(i); } }]]]
  • 61. Don’t be afraid! Performance is not a problem (when UniTask is used). Practice has already been established (when UniTask is used). There’s almost no damage from overdoing things (strongly speaking, asynchronous pollution). It’s at a level at which there’s no reason not to go for it, so GO right now. Recommended to use with UniRx.Async async/await has been redesigned for Unity with performance and user-friendliness. Everything used in Unity has been made capable of await. Don’t be afraid of normal Task not being used! Let’s traverse the leading edge, surpassing all language and the ordinary .NET!