//子线程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();
}
}