一 什么是多线程

1、 什么是进程?一个 exe 运行一次就会产生一个进程,一个 exe 的多个进程之 间数据互相隔离。

2、 一个进程里至少有一个线程:主线程。我们平时写的控制台程序默认就是单线程的,代 码从上往下执行,一行执行完了再执行下一行;

3、 什么是多线程:一个人两件事情同时做效率高。同一时刻一 个人只能干一件事情,其实是在“快速频繁切换”,如果处理不当可能比不用多线程效率还低

二  Thread 对象

2.1 thread基础写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        public static void ThreadTest()
        {
            int a = 0;
            Thread thread1 = new Thread(m=>
            {
                for (int i = 0; i < 20; i++)
                {
                    a = a + 1;
                    Console.WriteLine("线程1:"+ a);
                }
            });
            Thread thread2 = new Thread(m =>
            {
            for (int i = 0; i < 20; i++)
            {
                    a = a + 1;
                Console.WriteLine("线程2:"+ a);
                }
            });
             
            thread1.Start();
            thread2.Start();
            Console.ReadKey();
        }

这段代码输出结果如下:

可以看出两个子线程启动后是并行执行的,所以输出结果没有按照顺序来

2.2 设置线程的优先级

thread1.Priority=ThreadPriority。。。

2.3  t1.Join()当前线程等待 t1 线程执行结束,实例如下:

这段代码执行过后输出的结果就是正常的从1输出到了40

public static void ThreadTest(){int a = 0;Thread thread1 = new Thread(m=> {for (int i = 0; i < 20; i++){a = a + 1;Console.WriteLine("线程1:"+ a);}});Thread thread2 = new Thread(m =>{//等待thread1线程任务完成后在执行thread1.Join();for (int i = 0; i < 20; i++){a = a + 1;Console.WriteLine("线程2:"+ a);}});//可以将参数传入到子线程中thread1.Start(a);//thread1.Join(); 或者将Join放在这里thread2.Start(a);Console.ReadKey();}

2.4 Interrupt方法

Interrupt 用于提前唤醒一个在 Sleep 的线程,Sleep 方法会抛出 ThreadInterruptedException 异常 代码如下:

代码输出到9的时候线程会休眠8秒钟,但是运行到主线程thread1.Interrupt()时,子线程会被唤醒,然后执行catch里面的Console.WriteLine("线程被唤醒");之后接着从10开始输出到2000。需要注意的是只有线程自身能让自身休眠

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static void ThreadTest2()
        {
            Thread thread1 = new Thread(() =>
            {
                for (int i = 0; i < 2000; i++)
                {
                    if (i==10)
                    {
                        //唤醒线程之后会引发ThreadInterruptedException类型的异常,所以需要try catch
                        try
                        {
                            //子线程休眠8秒钟
                            Thread.Sleep(8000);
                        }
                        catch (ThreadInterruptedException ex)
                        {
                            Console.WriteLine("线程被唤醒");
                        }
                    }
                    Console.WriteLine(i);
                }
            });
            thread1.Start();
            //提前唤醒在沉睡的子线程
            Thread.Sleep(3000);
            thread1.Interrupt();
            Console.ReadKey();
        }

  

三 线程池

3.1、线程池:因为每次创建线程、销毁线程都比较消耗 cpu 资源,因此可以通过线程池进行 优化。线程池是一组已经创建好的线程,随用随取,用完了不是销毁线程,然后放到线程池 中,供其他人用。

3.2、用线程池之后就无法对线程进行精细化的控制了(线程启停、优先级控制等)

3.3、ThreadPool 类的一个重要方法:

  static bool QueueUserWorkItem(WaitCallback callBack)

  static bool QueueUserWorkItem(WaitCallback callBack, object state)

3.4、除非要对线程进行精细化的控制,否则建议使用线程池,因为又简单、性能调优又更好。

1
2
3
4
5
6
7
8
9
10
11
12
13
//QueueUserWorkItem是一个静态方法不需要New
public static void ThreadPool()
{
    System.Threading.ThreadPool.QueueUserWorkItem(m=>
    {
        for (int i = 0; i < 1000; i++)
        {
            i++;
            Console.WriteLine(i);
        }
    });
    Console.ReadKey();
}

  

四 TPL风格的异步方法

TPL(Task Parallel Library)是.Net 4.0 之后带来的新特性,更简洁,更方便。现在在.Net 平台下已经大面积使用。

注意方法中如果有 await,则方法必须标记为 async,不是所有方法都可以被轻松的标记 为 async。WinForm 中的事件处理方法都可以标记为 async、MVC 中的 Action 方法也可以标 记为 async、控制台的 Main 方法不能标记为 async。  TPL 的特点是:方法都以 XXXAsync 结尾,返回值类型是泛型的 Task<T>。  TPL 让我们可以用线性的方式去编写异步程序,不再需要像 EAP 中那样搞一堆回调、逻 辑跳来跳去了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//TPL风格返回的Task<T> 泛型的数据
//await 关键字等待异步方法返回
public static async void Task()
{
    WebClient wc = new WebClient();
    string s= await wc.DownloadStringTaskAsync("http://www.baidu.com");
    Console.WriteLine(s);
    Console.ReadKey();
}
public static void Task2()
{
    WebClient wc = new WebClient();
    //若果不使用await关键字就得使用Task<string>类型来接收数据
    Task<string> s2 = wc.DownloadStringTaskAsync("http://www.baidu.com");
    Console.ReadKey();
}

  

自己编写一个TPL风格的异步方法:

使用了async关键字就必须返回Task泛型数据类型的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Task<string> StringAsync()
{
   return Task.Run(() =>
    {
        Thread.Sleep(5000);
        return "hehe";
    });
           
}
// GET: Home
public async Task<ViewResult> Index()
{
    var s = await StringAsync();
    return View();
}

  

如果返回值就是一个立即可以随手可得的值,那么就用 Task.FromResult()  如果是一个需要休息一会的任务(比如下载失败则过 5 秒钟后重试。主线程不休息,和 Thread.Sleep 不一样),那么就用 Task.Delay()。 3、Task.Factory.FromAsync()把 IAsyncResult 转换为 Task,这样 APM 风格的 api 也可以用 await 来调 用。 4、编写异步方法的简化写法。如果方法声明为 async,那么可以直接 return 具体的值,不再用创建 Task,由编译器创建 Task:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static async Task<int> F1Async()
{
     return 1;
 }
  
static Task<int> F2Async()
     return Task.FromResult(3);
}
  
static Task<int> F3Async()
     return Task.Run(()=> { 
     return 1 + 3;  });
}

一定要让 async 的传染性(调用异步方法要用 await,用了 await 方法就要声明为 async,调 用我这个 async 方法的地方必须要 await……)不要轻易直接调用 Task 的 Wait、WaitAll 等方 法。等待一个用 await,而不是 task.Wait();等待多个用 await Task.WhenAll(),而不是 Task.WaitAll()

c#之多线程之为所欲为相关推荐

  1. java多线程的安全问题与死锁(面向厕所编程)

    大纲:java线程知识体系 这是不安全的问题代码 /* Windows模拟的是售票窗口类 共享数据:多个线程共同操作的数据,即本案例中的tocketNum*/ public class Windows ...

  2. 实现多线程的几种方式

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/king_kgh/article/details/78213576 多线程的形式上实现方式主要有两种, ...

  3. java多线程的6种实现方式详解

    多线程的形式上实现方式主要有两种,一种是继承Thread类,一种是实现Runnable接口.本质上实现方式都是来实现线程任务,然后启动线程执行线程任务(这里的线程任务实际上就是run方法).这里所说的 ...

  4. Java 多线程概述

    多线程技术概述 1.线程与进程 进程:内存中运行的应用程序,每个进程都拥有一个独立的内存空间. 线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换.并发执行,一个进程最少有一个线程, ...

  5. Java 多线程的基本方式

    Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

  6. RPC 笔记(08)— socket 通信(多进程多线程服务器)

    在上一节中如果并行的客户端连接数超过了默认开启进程的数量,那么后来的客户端请求将会阻塞,为了不阻塞新的客户端,我们可以将进程的单线程改成多线程即可. ​ 服务端代码: import json impo ...

  7. Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步

    主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...

  8. Python 多线程总结(1)- thread 模块

    thread 模块 1. 单线程 首先看下单线程程序运行的例子,如下所示, import timedef loop0():print 'start loop0 begin', time.ctime() ...

  9. Python多线程调试

    有时候程序是多线程的,调试的时候可能跑到别的线程了. 这个时候把thread.start变成threa.run就好了,就会执行完当前线程再执行下一个. for thread in threads:th ...

最新文章

  1. 中国“芯”的突破攻略——智源大会“智能体系架构与芯片”论坛发布
  2. Java.util包中常用的类
  3. yii2 layout main.php,yii2 – 如何将参数传递给mainLayoutAsset.php文件?
  4. 零配置 之 Spring 注解实现Bean依赖注入
  5. 如何导入一个项目 myeclipse
  6. Spring Boot + Jersey发生FileNotFoundException (No such file or directory)
  7. ThingsBoard 提示Too many updates!
  8. 拓端tecdat|sas神经网络:构建人工神经网络模型来识别垃圾邮件
  9. xtrabackup备份原理
  10. 信息检索的过去 当前 未来-------浅层分析报告
  11. 2023年东北大学理学院数学考研必看成功上岸前辈复习经验分享
  12. java中System类详解
  13. CCPROXY漏洞利用
  14. 电商“论贱”血拼 传统书店该何去何从
  15. Doctype作用?标准模式与兼容模式各有什么区别?
  16. 2012年度x86服务器虚拟化基础设施魔力象限,五载解读!Gartner x86虚拟化魔力象限...
  17. 中国书信礼仪 (三)
  18. 【Java余元面向对象】(23)抽象方法/抽象类
  19. uniapp 拉起微信客服功能
  20. Python爬虫种类、法律、轮子,轮子们,你们辛苦了

热门文章

  1. 不想用鸿蒙系统怎么办,华为鸿蒙系统出大BUG!网友:这再也不是用户想要的鸿蒙系统...
  2. Springboot 多模块项目创建与配置
  3. 如何创建一个简单 APT 仓库
  4. spring IOC 装配一个bean
  5. 操作系统第二章总结/
  6. JQuery基本获取值的方式
  7. 诗与远方:无题(八十五)- 无字天书
  8. Mybatis的查询、关联查询
  9. Halcon 轮廓合并算子
  10. golang游戏服务器框架_Go开源游戏服务器框架——Pitaya