C#线程和Task


基础概念

  • 多线程如果给每个线程分配一个CPU这是最优情况,但是线程数量是大于电脑CPU数量的。所以操作系统通过 时间分片操作模拟并行操作,操作系统通过极快的速度从一个线程切换到另一个线程,并且这个操作叫做上下文切换。注意上下文切换存在很大的开销
  • 多线程存在的问题
  1. 程序的不确定性 2个线程不断的切换无法确定线程执行顺序
  2. 内存模型的复杂性 2个线程去访问内存的某个字段,不会去直接访问内存。而是去访问处理器的高速缓冲区,这个缓冲区定时更新。这个我的理解是A线程修改了字段,但是未同步。B访问了,得到了不同的值。
  3. 死锁 直接上图

线程API

Task:https://www.cnblogs.com/mq0036/p/9040614.html
#async/await:
await相当于分支;

#Task:
task.Result task函数具有返回值
task 4 种启动方式:
1、run
2、start
3、TaskFactory
4、RunSynchronously 同步执行,阻塞主线程
task控制:
1、task1.Wait()等待某个
2、Task.WaitAll等待所有完成
3、Task.WaitAny等待任何一个
123均为阻塞线程
4、 task1.ContinueWith 一个task执行完执行下一个
5、CancellationTokenSource 调用Cannel取消任务
6、WhenAny、WhenAll和Task.Factory.ContinueWhenAll、Task.Factory.ContinueWhenAny。执行后续操作。不会阻塞

//跑一遍 看对应debug和线程id就明白了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using System.Threading;

public class TestManager : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        AsyncPrintHelloWorld();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public async static void AsyncPrintHelloWorld()
    {
        Debug.Log("异步方法调用开始");
        Debug.Log("开始前id" + Thread.CurrentThread.ManagedThreadId); //测试结果id:1
        //这里开启了4个异步方法、并且是在同时执行
        var result1 = TMothd1();
        var result2 = TMothd2();
        var result3 = TMothd3();
        var result4 = TMothd4();
        Debug.Log("异步方法完成");
        int r1 = await result3;   //这里先等待时间最长的函数。会发现1、2、3均在在执行并完成,只是这里将主线程给阻塞了,无法继续执行下去,其实已经完成了
        Debug.Log("最长耗时任务完成");
        int r2 = await result1;
        int r3 = await result2;
        int r4 = await result4;

        Debug.Log("完成所有异步后函数线程id" + Thread.CurrentThread.ManagedThreadId); //测试结果id:1,也在主线程
        Debug.Log(r1+"-"+ r2 + "-" + r3 + "-" + r4);
    }

    /// <summary>
    /// 这里测试一下,在这个异步函数中 await 前后的线程情况
    /// </summary>
    /// <returns></returns>
    public async static Task<int> TMothd1()
    {
        Debug.Log("函数1,await前线程id为:" + Thread.CurrentThread.ManagedThreadId); //测试结果id:1,在主线程
        return await Task.Factory.StartNew(() =>
        {
            Thread.Sleep(5 * 1000); //5秒
            Debug.Log("TMothd1 中,当前线程id为" + Thread.CurrentThread.ManagedThreadId);//测试结果id:35
            return 1;
        });
    }

    public async static Task<int> TMothd2()
    {
        return await Task.Factory.StartNew(() =>
        {
            Thread.Sleep(10 * 1000);//10秒
            Debug.Log("TMothd2 完成,当前线程id为" + Thread.CurrentThread.ManagedThreadId);//测试结果id:38
            return 2;
        });
    }
    public async static Task<int> TMothd3()
    {
        return await Task.Factory.StartNew(() =>
        {
            Thread.Sleep(15 * 1000);//15秒/耗时最长
            //Debug.Log("TMothd3 完成");
            return 3;
        });
    }


    public async static Task<int> TMothd4()
    {
        Debug.Log("刚进入函数4线程id为:" + Thread.CurrentThread.ManagedThreadId); // 测试结果id:1,也在主线程
        Task<int> task = Task.Factory.StartNew(() =>
        {
            Thread.Sleep(3 * 1000); //3秒s
            Debug.Log("TMothd4 完成,当前线程id为" + Thread.CurrentThread.ManagedThreadId); //在另一个线程
            return 3;
        });
        return await task;
        
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值