Async/Await vs Unity Coroutine

  • 4403
  • 0

Async/Await學習筆記

1. Coroutine不能回傳值;Async/Await可以

public class CoroutineSample : MonoBehaviour
{
    private void Start()
    {
        StartCoroutine(routine());
    }

    private IEnumerator routine()
    {
        yield return null;
    }
}
public class AsyncReturnValue : MonoBehaviour
{
    private async void Start()
    {
        int result = await GetCount();
    }

    private async Task<int> GetCount()
    {
        return await Task.FromResult<int>(1);
    }
}

2. Coroutine每偵一次循環;Async/Await同步執行

public class CoroutineFrame : MonoBehaviour
{
    private void Start()
    {
        StartCoroutine(Routine());
    }

    private IEnumerator Routine()
    {
        Debug.Log($"Frame: {Time.frameCount}");
        yield return null;
        Debug.Log($"Frame: {Time.frameCount}");
    }

    //Outputs:
    //Frame:1
    //Frame:2
}
public class AsyncFrame : MonoBehaviour
{
    private async void Start()
    {
        Debug.Log($"Frame: {Time.frameCount}");
        await Function();
        Debug.Log($"Frame: {Time.frameCount}");
    }

    private async Task Function()
    {
        await Task.Yield();
    }

    //Outputs:
    //Frame:1
    //Frame:1
}

3. Coroutine依賴於Monobehaviour;Async/Await為C#語法

4. Coroutine不支援try/catch;Async/Await支援

5. Coroutine依賴的Monobehaviour被移除將停止執行可能造成記憶體未釋放;Async/Await會照常執行

public class CoroutineLeak : MonoBehaviour
{
    private IEnumerator ShowTexture(RawImage container)
    {
        var texture = new RenderTexture(512, 512, 0);
        container.texture = texture;
        for(int i = 0; i < 100; ++i)
        {            
            yield return null;
        }
        //迴圈結束前MonoBehaviour被刪除將不會執行
        texture.Release();
    }
}
public class AsyncLeak : MonoBehaviour
{
    async Task ShowTexture(RawImage container)
    {
        var texture = new RenderTexture(512, 512, 0);
        container.texture = texture;
        for (int i = 0; i < 100; ++i)
            await Task.Yield();

        //不會因MonoBehaviour被刪除而停止執行
        texture.Release();
    }
}

6. Async/Await提供較為詳細的Call Stack 

7. Coroutine生命週期依賴於Monobehaviour;Async/Await則較靈活

8. 針對I/O-bound code使用Task或Task<T>等不需建立thread的方法;CPU-bound則使用Task.Run等方法建立背景執行緒做CPU運算

Reference:

https://www.youtube.com/watch?v=7eKi6NKri6I

https://docs.microsoft.com/zh-tw/dotnet/csharp/async