当前位置: 首页 > news >正文

C# 多线程

文章目录

  • C# 多线程
    • 进程与线程
    • 无参数的子线程
    • 带参数的子线程
      • 运行结果
    • 销毁线程 Abort()
      • 运行结果
    • ThreadPool和Task
      • 运行结果
    • 异步与同步
      • 运行结果
    • lock
      • 单线程
        • 运行结果
      • 多线程
        • 运行结果
      • 使用lock
        • 运行结果

C# 多线程

进程与线程

进程:进程就是一个应用程序,对电脑的各种资源的占用

线程:线程是程序执行的最小单位,任何操作都是线程完成的,线程依托进程存在的,一个进程可以有多个线程

无参数的子线程

 public static void ChildThread1(){Console.WriteLine("Child thread1 is starts");}

带参数的子线程

ChildThread2是带参数的子线程,所以要使用ParameterizedThreadStart类型的委托来指定子线程
如果使用的是不带参数的委托,不能使用带参数的Start方法运行线程,否则系统会抛出异常。
但使用带参数的委托,可以使用thread.Start()来运行线程,这时所传递的参数值为null。

特别注意:ParameterizedThreadStart委托的参数类型必须是object的

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static void ChildThread1(){Console.WriteLine("Child thread1 is starts");}//注意:ParameterizedThreadStart委托的参数类型必须是object的public static void ChildThread2(object obj){Console.WriteLine("Child thread2 is starts,the parameter is {0}", obj);}public static void Main(){ThreadStart thread1 = new ThreadStart(ChildThread1); //通过ThreadStart委托指定子线程的方法ParameterizedThreadStart thread2 = new ParameterizedThreadStart(ChildThread2); //有参的委托Console.WriteLine("MainThread:Creating the child thread1");Console.WriteLine("MainThread:Creating the child thread2");Thread childThread1 = new Thread(thread1); //创建子线程1Thread childThread2 = new Thread(thread2);//创建子线程2childThread1.Start();    //运行子线程1childThread2.Start("子线程2的参数");//运行子线程2,传递参数,//如果使用的是不带参数的委托,不能使用带参数的Start方法运行线程,否则系统会抛出异常。//但使用带参数的委托,可以使用thread.Start()来运行线程,这时所传递的参数值为null。Console.ReadKey();}}
}

运行结果

在这里插入图片描述

销毁线程 Abort()

使用Abort()中止子线程.
通过抛出 threadabortexception 在运行时中止线程。这个异常不能被捕获,如果有 finally 块,控制会被送至 finally 块。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static void ChildThread1(){Console.WriteLine("Child thread1 is starts");}//注意:ParameterizedThreadStart委托的参数类型必须是object的public static void ChildThread2(object obj){Console.WriteLine("Child thread2 is starts,the parameter is {0}", obj);}public static void ChildThread3(){try{Console.WriteLine("Child thread3 starts");for (int i = 0; i < 5; i++){Thread.Sleep(100);Console.WriteLine(i);}Console.WriteLine("Child Thread3 Completed");}catch (ThreadAbortException e){Console.WriteLine("Thread Abort Exception");}finally{Console.WriteLine("Couldn't catch the thread Exception");}}public static void Main(){ThreadStart thread3 = new ThreadStart(ChildThread3);Console.WriteLine("MainThread:Creating the child thread3");Thread thread = new Thread(thread3);thread.Start();//停止主线程1000Thread.Sleep(2000);Console.WriteLine("In Main: Aborting the Child thread");thread.Abort();Console.ReadKey();}}
}

运行结果

在这里插入图片描述

ThreadPool和Task

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static Thread t = null;public static void ChildThread1(){int i = 5;while (i > 0){Console.WriteLine(string.Format("线程【1】的i:{0} ", i));Thread.Sleep(10);i--;}Console.WriteLine("线程【1】结束");//Console.WriteLine("Child thread1 is starts");}//注意:ParameterizedThreadStart委托的参数类型必须是object的public static void ChildThread2(object obj){int i = 5;while (i > 0){Console.WriteLine(string.Format("线程【2】的i:{0} ", i));Thread.Sleep(10);i--;}Console.WriteLine("线程【2】结束");}public static void ChildThread3(){int i = 5;while (i > 0){Console.WriteLine(string.Format("线程【3】的i:{0} ", i));Thread.Sleep(10);i--;}Console.WriteLine("线程【3】结束");}public static void Main(string[] args){t = new Thread(new ThreadStart(ChildThread1));t.Start();//用线程池ThreadPool.QueueUserWorkItem(ChildThread2, new object());//用Task方法创建System.Threading.Tasks.Task.Factory.StartNew(ChildThread3);Console.ReadLine();}}
}

运行结果

在这里插入图片描述
线程都是独立的,不会互相影响。

异步与同步

C# 5.0引入了异步方法(Async Methods)的概念,使得编写异步代码变得更加容易。异步方法使用async关键字标记,返回类型必须是Task或Task,方法中使用await关键字来等待异步操作完成。通过使用异步方法,可以在不阻塞主线程的情况下执行耗时操作,从而提高程序的并发性和响应性。示例如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static async Task Main(string[] args){await DownloadWebsiteAsync();Console.ReadKey();}static async Task DownloadWebsiteAsync(){using (HttpClient client = new HttpClient()){string website = "https://www.example.com";string content = await client.GetStringAsync(website);Console.WriteLine("等待异步执行完成");}}}
}

运行结果

在这里插入图片描述

lock

如果你想控制多线程的线程的执行顺序,就需要用到lock

参考链接:https://blog.csdn.net/u012563853/article/details/124767902

单线程

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{static int a = 0;static int b = 0;private static object o = new object();static void Main(string[] args){methodA();methodB();Console.ReadKey();}private static void methodA(){Console.WriteLine("我是A方法");}private static void methodB(){Console.WriteLine("我是B方法");}private static void methodC(){Console.WriteLine("我是C方法,是随机出现的");}}
}

这样是按顺序执行的,因为是单线程的,先执行methodA,再去执行methodB
在这里插入图片描述

运行结果

在这里插入图片描述

多线程

我们增加了多线程,就是让A和B方法同时执行,此时,结果就是不可控制的。有时候先执行B方法,有时候先执行A方法。先执行B方法。

在这里插入图片描述

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{static int a = 0;static int b = 0;private static object o = new object();static void Main(string[] args){//methodA();//methodB();Thread t1 = new Thread(methodA);Thread t2 = new Thread(methodB);t1.Start();t2.Start();Console.ReadKey();}private static void methodA(){a = 1;Console.WriteLine("我是A方法,a=" + a);Thread.Sleep(2000); //暂停5秒b = 2;Console.WriteLine("我是A方法,b=" + b);}private static void methodB(){a++;Console.WriteLine("我是B方法,a=" + a);Thread.Sleep(1000); //暂停1秒b++;Console.WriteLine("我是B方法,b=" + b);}private static void methodC(){Console.WriteLine("我是C方法,是随机出现的");}}
}
运行结果

在这里插入图片描述
所以,我们可以使用lock去锁住代码段,锁住的这段代码,此时只能有一个线程去访问,只有等这个线程访问结束了,其他线程才能访问。

使用lock

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{static int a = 0;static int b = 0;private static object o = new object();static void Main(string[] args){//methodA();//methodB();Thread t1 = new Thread(methodA);Thread t2 = new Thread(methodB);t1.Start();t2.Start();Console.ReadKey();}private static void methodA(){lock (o){a = 1;Console.WriteLine("我是A方法,a=" + a);Thread.Sleep(2000); //暂停5秒b = 2;Console.WriteLine("我是A方法,b=" + b);}}private static void methodB(){lock (o){a++;Console.WriteLine("我是B方法,a=" + a);Thread.Sleep(1000); //暂停1秒b++;Console.WriteLine("我是B方法,b=" + b);}}private static void methodC(){Console.WriteLine("我是C方法,是随机出现的");}}
}

在这里插入图片描述

运行结果

在这里插入图片描述
这样也是等效的:
在这里插入图片描述
Enter相当于进入这个代码块,Exit是退出这个代码块。当这个代码块再运行的时候,其他线程就不能访问。Monitor中的{}可以去掉,不影响。
在这里插入图片描述

http://www.lryc.cn/news/330180.html

相关文章:

  • 快速安装sudachipy日语包
  • 蓝桥杯刷题day13——乘飞机【算法赛】
  • 大模型量化技术-BitsAndBytes
  • EasyExcel 复杂表头的导出(动态表头和静态表头)
  • centos7 fatal error: curl/curl.h: No such file or directory
  • 【Linux】自定义协议+序列化+反序列化
  • 常见故障排查和优化
  • 选择华为HCIE培训机构有哪些注意事项
  • python怎么处理txt
  • SAMRTFORMS 转换PDF 发送邮件
  • 探讨在大数据体系中API的通信机制与工作原理
  • 算法打卡day23
  • 每天五分钟深度学习:神经网络和深度学习有什么样的关系?
  • 基于PSO优化的CNN-LSTM-Attention的时间序列回归预测matlab仿真
  • 物联网监控可视化是什么?部署物联网监控可视化大屏有什么作用?
  • 设计一个Rust线程安全栈结构 Stack<T>
  • Docker Desktop 在 Windows 上的安装和使用
  • 2024年最受欢迎的 19 个 VS Code 主题排行榜
  • 突破编程_C++_网络编程(OSI 七层模型(物理层与数据链路层))
  • Spring boot如何使用redis缓存
  • 红蓝色WordPress外贸建站模板
  • python爬虫----了解爬虫(十一天)
  • 碳素光线疗法与宠物健康
  • 展锐平台camera添加底层水印
  • OSX-02-Mac OS应用开发系列课程大纲和章节内容设计
  • 热门IT【视频教程】-华为/思科/红帽/oracle
  • HCTNet:一种用于乳腺超声图像分割的混合CNN-transformer
  • 766. 托普利茨矩阵
  • 基于STM32的汽车防窒息系统
  • GoogleNet神经网络介绍