多线程和异步

多线程

线程概念

  1. 线程
  • 进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程
  1. 前台线程/后台线程
  • 结束进程时,需要等前台线程结束,才能完全结束,而后台线程会在进程结束时同时结束

Thread

  1. 默认前台线程
  2. 有线程的取消、完成、失败通知等交互性操作
  3. 通过jion阻塞,达到线程执行的先后次序

ThreadPool

  1. 默认后台线程
  2. 无线程的取消、完成、失败通知等交互性操作
  3. 可以减少每次创建线程的开销
static void Main(string[] args)
{
    ThreadPool.SetMinThreads(12, 12);
    for (int i = 0; i < 10; i++)
    {
        int k = i;
        ThreadPool.QueueUserWorkItem(GetThreadPool, i);
    }
    //Console.WriteLine($"主线程执行完毕!{DateTime.Now}");
    Console.Read();
}
static void GetThreadPool(object index)
{
    Thread.Sleep(1000);
    Console.WriteLine($"异步运行,第{index}个{DateTime.Now}");
}

返回

异步运行,第0个2021/01/26 15:37:49
异步运行,第2个2021/01/26 15:37:49
异步运行,第7个2021/01/26 15:37:49
异步运行,第8个2021/01/26 15:37:49
异步运行,第9个2021/01/26 15:37:49
异步运行,第1个2021/01/26 15:37:49
异步运行,第6个2021/01/26 15:37:49
异步运行,第4个2021/01/26 15:37:49
异步运行,第3个2021/01/26 15:37:49
异步运行,第5个2021/01/26 15:37:49

可以通过SetMaxThreads来设置一次性最大创建多少个线程,如Max为8,上面就会分两次返回结果的,但Max值不能小于当前服务器最低的线程数,也可以设置SetMinThreads数来设置当前最低线程数,同样不能低于服务器实际最低线程数

ThreadPool.SetMaxThreads(8, 8);

返回

异步运行,第3个2021/01/26 15:41:02
异步运行,第2个2021/01/26 15:41:02
异步运行,第1个2021/01/26 15:41:02
异步运行,第0个2021/01/26 15:41:02
异步运行,第5个2021/01/26 15:41:02
异步运行,第6个2021/01/26 15:41:02
异步运行,第4个2021/01/26 15:41:02
异步运行,第7个2021/01/26 15:41:02
异步运行,第8个2021/01/26 15:41:03
异步运行,第9个2021/01/26 15:41:03

异步

Task

异步和同步

  • 发起一个请求,等待到它运行完成即为同步
  • 发起一个请求,不等待结果,可以先去执行后面的业务,即为异步

异步调用方式

Task task1 = new Task(()=>{
    Console.WriteLine("异步运行1");
});
task1.Start();

Task task2 = Task.Factory.StartNew(()=>{
     Console.WriteLine("异步运行2");
});

Task task3 = Task.Run(()=>{
     Console.WriteLine("异步运行3");
});

异步完成

static void Main(string[] args)
{
    Task<string> task = new Task<string>(() =>
    {
        Console.WriteLine($"异步运行");
        return "123";
    });
    task.Start();
    task.ContinueWith(t => {
        Console.WriteLine($"异步完成,{t.Result}"); 
    });
    Console.WriteLine($"异步开始");
    Thread.Sleep(5 * 1000);
    Console.Read();
}

返回结果

异步开始
异步运行
异步完成,123

扩展还可以使用

Task.WhenAll(task1, task2).ContinueWith((t) => {
    Thread.Sleep(100);
    Console.WriteLine("执行后续操作完毕!");
});
Task.WhenAny(task1, task2).ContinueWith((t) => {
    Thread.Sleep(100);
    Console.WriteLine("执行后续操作完毕!");
});

异步阻塞

正常代码

static void Main(string[] args)
{
    Task<string> task1 = GetAwaitTask(1, "1");
    Task<string> task2 = GetAwaitTask(2, "2");
    Task<string> task3 = GetAwaitTask(1, "3");
    Task<string> task4 = GetAwaitTask(1, "4");
    //Task.WaitAll(new Task[] { task1, task2,task3,task4 });       
    Console.WriteLine($"主线程执行开始!{DateTime.Now}");
    //Console.WriteLine($"主线程执行完毕!{DateTime.Now}");
    Console.Read();
}
static Task<string> GetAwaitTask(int nMs, string index)
{
    Task<string> task = Task.Run(() =>
    {
        Thread.Sleep(nMs * 1000);
        Console.WriteLine($"异步运行,第{index}个{DateTime.Now}");
        return $"ceshiyixia{index}";
    });
    Console.WriteLine($"异步开始,第{index}个{DateTime.Now}");
    return task;
}

返回结果

异步开始,第1个2021/01/26 11:17:00
异步开始,第2个2021/01/26 11:17:00
异步开始,第3个2021/01/26 11:17:00
异步开始,第4个2021/01/26 11:17:00
主线程执行开始!2021/01/26 11:17:00
异步运行,第1个2021/01/26 11:17:01
异步运行,第3个2021/01/26 11:17:01
异步运行,第4个2021/01/26 11:17:01
异步运行,第2个2021/01/26 11:17:02

增加WaitAll后,返回

异步开始,第1个2021/01/26 11:17:49
异步开始,第2个2021/01/26 11:17:49
异步开始,第3个2021/01/26 11:17:49
异步开始,第4个2021/01/26 11:17:49
异步运行,第1个2021/01/26 11:17:50
异步运行,第3个2021/01/26 11:17:50
异步运行,第4个2021/01/26 11:17:50
异步运行,第2个2021/01/26 11:17:51
主线程执行开始!2021/01/26 11:17:51

增加WaitAny后

Task.WaitAny(new Task[] { task1, task2,task3,task4 });           

返回

异步开始,第1个2021/01/26 11:18:22
异步开始,第2个2021/01/26 11:18:22
异步开始,第3个2021/01/26 11:18:22
异步开始,第4个2021/01/26 11:18:22
异步运行,第1个2021/01/26 11:18:23
主线程执行开始!2021/01/26 11:18:23
异步运行,第3个2021/01/26 11:18:23
异步运行,第4个2021/01/26 11:18:23
异步运行,第2个2021/01/26 11:18:24

async/await

static void Main(string[] args)
{
    Console.WriteLine(GetAwaitTask(1,"1"))
    Console.WriteLine(GetAwaitTask(2,"2"));
    Console.WriteLine(GetAwaitTask(1,"3"));
    Console.WriteLine(GetAwaitTask(1,"4"));
    Console.WriteLine("主线程异步开始");
    Thread.Sleep(5 * 1000);
    Console.Read();
}

async static Task<string> GetAwaitTask(int nMs,string index)
{
    string task = await Task.Run(() =>
    {
        Console.WriteLine($"异步运行,第{index}个{DateTime.Now}");
        Thread.Sleep(nMs*1000);
        return $"ceshiyixia{index}";
    });
    Console.WriteLine($"异步开始,第{index}个{DateTime.Now}");
    return task;
}

返回结果

System.Threading.Tasks.Task`1[System.String]
System.Threading.Tasks.Task`1[System.String]
System.Threading.Tasks.Task`1[System.String]
System.Threading.Tasks.Task`1[System.String]
主线程异步开始
异步运行,第1个2021/01/26 10:54:09
异步运行,第3个2021/01/26 10:54:09
异步运行,第2个2021/01/26 10:54:09
异步运行,第4个2021/01/26 10:54:09
异步开始,第1个2021/01/26 10:54:10
异步开始,第3个2021/01/26 10:54:10
异步开始,第4个2021/01/26 10:54:10
异步开始,第2个2021/01/26 10:54:11

同样可以通过GetAwaitTask(1,“1”).Result的方式,阻塞,按顺序返回;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值