Unity-子线程async与协程比较

//子线程async与协程比较
//1 协程 2个缺点:没有返回值,yield语句无法放入try catch中
//2 async 可以规避协程的没有返回值,yield语句无法放入try catch中2个缺点
//3 协程回调
//4 ayync 回调
//5 task 异步的队列逐个执行。
//6 await Task.Run(() =>{};里面的代码是是子线程,协程是主线程里的协同线程,严格意义偏主线程里执行。

//子线程async与协程比较
//1 协程 2个缺点:没有返回值,yield语句无法放入try catch中
//2 async 可以规避协程的没有返回值,yield语句无法放入try catch中2个缺点
//3 协程回调
//4 ayync 回调
//5 task 异步的队列逐个执行。
//6 await Task.Run(() =>{};里面的代码是是子线程,协程是主线程里的协同线程,严格意义偏主线程里执行。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using DG.Tweening;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class Demo : MonoBehaviour
{
    public Image move;
    public Image myImage;
    public Image myImage2;
    List<Sprite> mySprite = new List<Sprite>();
    List<GameObject> gameObjects = new List<GameObject>();


    void Start()
    {
        
        Test1_1();
        Test1_2();
        StartCoroutine(Test2_1());
        StartCoroutine(Test2_2());

        Task<int> testInt = Test1_3();
        Debug.Log($"testInt.Result = {testInt.Result}");


        //协程模拟有返回值的做法
        //一般lambda表达式带参数意义不是很大,如果需要带参数,如下的实例比较好。
        //比较有意义的带参数的使用的lambda表达式
        //拿到图片的路径,转换为Texure,然后把Texure转换为Image的sprite,Image显示出来
        //路径为:Assets/StreamingAssets/a.png
        StartCoroutine(GetLocalTexture(StreamingAssetsPath("a.png"), (texture) =>
        {
            //图片资源, new Vector4(40, 40, 40, 42))表示图片在slice模式下切四个角的大小。
            Sprite spriteFromWeb =
            Sprite.Create(
            texture,
            new Rect(0, 0, texture.width, texture.height),
            new Vector2(0, 0),
            100,
            0,
            SpriteMeshType.Tight,
            new Vector4(40, 40, 40, 42));

            myImage.sprite = spriteFromWeb;
        }));


        GetLocalTexture2(StreamingAssetsPath("a.png"), (texture) =>
        {
            //图片资源, new Vector4(40, 40, 40, 42))表示图片在slice模式下切四个角的大小。
            Sprite spriteFromWeb =
            Sprite.Create(
            texture,
            new Rect(0, 0, texture.width, texture.height),
            new Vector2(0, 0),
            100,
            0,
            SpriteMeshType.Tight,
            new Vector4(40, 40, 40, 42));

            myImage2.sprite = spriteFromWeb;
        });

        //异步子线程队列
        //通过Task(封装过的特殊的线程),可以实现线程的队列逐个执行
        Task t1 = new Task(MyThreadMethod1);
        t1.Start();
        Task t2 = t1.ContinueWith(MyThreadMethod2);
        Task t3 = t2.ContinueWith(MyThreadMethod3);
    }

    public void MyThreadMethod1()
    {
        Debug.Log("MyThreadMethod1.");
    }
    public void MyThreadMethod2(Task t)
    {
        Debug.Log("MyThreadMethod2. t.id=" + t.Id);
    }
    public void MyThreadMethod3(Task t)
    {
        Debug.Log("MyThreadMethod3. t.id=" + t.Id);
    }


    //方法用async标记后,如果方法内没有await,这个方法的调用和普通方法的调用没有区别。
    //有await时,在await之前的代码依然在主线程内按顺序执行。
    //await Task.Run(() =>{};里面的代码是是子线程
    async void Test1_1()
    {
        Debug.Log("Test1_1-1");
        try
        {
            await Task.Run(() =>
            {
                //子线程执行
                Debug.Log("try Test1_1");
            });

        }
        catch (Exception ex)
        {

        }

        Debug.Log("Test1_1-2");
    }


    //方法用async标记后,如果方法内没有await,这个方法的调用和普通方法的调用没有区别。
    //有await时,在await之前的代码依然在主线程内按顺序执行。
    //await Task.Run(() =>{};里面的代码是子线程,await Task.Delay(2000);后面是主线程执行
    //async只能标记返回型为void、Task或者Task的方法
    async void Test1_2()
    {
        Debug.Log("Test1_2");
        try
        {
            //毫秒
            await Task.Delay(2000);
            //主线程执行
            Debug.Log("try Test1_2");
        }
        catch (Exception ex)
        {

        }
    }
    //可以有返回值
    async Task<int> Test1_3()
    {
        //毫秒
        await Task.Delay(0);
        //主线程执行
        return 10;
    }

    IEnumerator Test2_1()
    {
        yield return null;
        try
        {
            //主线程执行
            Debug.Log("try Test2_1");
        }
        catch (Exception ex)
        {

        }
    }

    IEnumerator Test2_2()
    {
        yield return new WaitForSeconds(2f);
        try
        {
            //会报错
            //yield return new WaitForSeconds(0.1f);
            //主线程执行
            Debug.Log("try Test2_2");
        }
        catch (Exception ex)
        {

        }
    }

    IEnumerator GetLocalTexture(string url, Action<Texture2D> actionResult)
    {
        UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url);
        yield return uwr.SendWebRequest();

        //uwr.SendWebRequest();
        //while (!uwr.isDone)
        //{
        //    yield return new WaitForSeconds(0.001f);
        //}

        Texture2D myTexture = null;
        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.Log($"GetLocalTexture www.error = {uwr.error}");
        }
        else
        {
            myTexture = ((DownloadHandlerTexture)uwr.downloadHandler).texture;
        }
        if (actionResult != null)
        {
            if (myTexture != null)
            {
                actionResult(myTexture);
            }
        }
    }

    async void GetLocalTexture2(string url, Action<Texture2D> actionResult)
    {
        Texture2D myTexture = null;
        UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url);
        uwr.SendWebRequest();

        while (!uwr.isDone)
        {
            await Task.Delay(1);
        }

        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.Log($"GetLocalTexture www.error = {uwr.error}");
        }
        else
        {
            myTexture = ((DownloadHandlerTexture)uwr.downloadHandler).texture;

            if (actionResult != null)
            {
                if (myTexture != null)
                {
                    actionResult(myTexture);
                }
            }
        }
    }

    public string StreamingAssetsPath(string pathName)
    {
        string path = "";
        if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.IPhonePlayer)
        {
            path = "file://" + Application.streamingAssetsPath + "/" + pathName;
        }
        else if (Application.platform == RuntimePlatform.Android)
        {
            path = Application.streamingAssetsPath + "/" + pathName;
        }
        return path;
    }



    private void Update()
    {
        //loadResourceTestAsync();
        //StartCoroutine(loadResourceTestIE());
    }

    //主线程执行
    public void loadResourceTest()
    {
        for (int i = 0; i < 1000; i++)
        {
            gameObjects.Add(new GameObject());
        }

        for (int i = 0; i < 1000; i++)
        {
            gameObjects[i].AddComponent<Image>();
            gameObjects[i].GetComponent<Image>().sprite = Resources.Load<Sprite>("b");
        }
    }

    async void loadResourceTestAsync()
    {
        await Task.Run(() =>
        {
            //子线程执行
            loadResourceTest();
        });

    }

    IEnumerator loadResourceTestIE()
    {
        yield return null;
        //主线程执行
        loadResourceTest();
    }


}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值