Unity Task 的用法

Unity 中的 Task 和 C# 中的 Task 不同。
unity Task 属于 netstandard.dll
在这里插入图片描述
C# Task 属于 mscorlib.dll
在这里插入图片描述
不同之处:
Unity 主线程调用 async 方法时,不论是 await 之前还是之后,代码都在主线程运行
c# 主线程调用async 方法时,await之前由主线程运行,await之后由子线程运行

unity 

async void task(){
语句1  //主线程调用
await taskMethod; //这里肯定是新线程执行了  
语句2 //主线程调用
}

unity 这个改动的好处是
unity 中使用 async 来处理异步方法就不需要考虑线程安全问题了,可以代替协程。
相比于协程,Task 更加灵活,不需要 Monobehavior 来开启,可以进行错误捕获。

要注意的地方:
第一:
在主线程使用 task.wait 方法 或者 使用 task.Result 会导致死锁

看个例子:
在这里插入图片描述
上面的代码运行Unity 后 Unity 会卡死。原因是产生了死锁!
分析下原因。
taskValue.wait 会去等待task001 任务的执行完成。
await task() 运行完成之后, 上下文切换到主线程。
也就是说 Debug.Log(“task001 end!”); 这个是需要主线程来执行的, 然而主线现在正在忙着执行taskValue.Wait(),没有空执行 Debug.Log(“task001 end!”); 这就导致了 task001 在等主线程来执行, 主线忙着等待 task001()。导致主线程无法向下执行。

第二: 值类型在await 值类型的方法中,代码获得的是值类型的一个拷贝。
例子:

public struct taskTest
{
    public int x;

    public  async Task task()
    {
        x = 100;

        Debug.Log("Task " + Thread.CurrentThread.ManagedThreadId);
        await task01();
        Debug.Log("Task01:" + Thread.CurrentThread.ManagedThreadId + "," + x);
    }

    public  Task task01()
    {
        return Task.Factory.StartNew(
            () => Thread.Sleep(5000)
            );
    }
}

monobehavior 中
    void Start()
    {
        task();
    }

    async Task task()
    {

        var tt = new taskTest();

        await tt.task();

        Debug.Log("xx:" + tt.x);

    }

在这里插入图片描述
可以发现子线程执行的 taskTest.task 方法中的实例 与 主线程中的 taskTest 实例不是同一个, taskTest.task 获得的是一个新副本。 具体原因就要看Unity源代码了。

参考
https://zhuanlan.zhihu.com/p/86168785

猜你喜欢

转载自blog.csdn.net/qq_27461747/article/details/107994633