【.NET Core】 多线程之(Thread)详解

简介: 【.NET Core】 多线程之(Thread)详解

一、概述

线程被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及复杂且耗时的操作,那么设置不同的线程执行路径往往事半功倍,让每个线程执行特定的工作任务。


线程是一个轻量级进程。一个使用线程的常见实例是操作系统中并行编程的实现。使用线程节省了CPU周期的浪费,同时提高了应用程序的效率。本文将讲详细讲解Thread线程的用法。


Thread类位于System.Threading命名空间下,System.Threading命名空间提供一些可以进行多线程编程的类和接口。除同步线程活动和访问数据的类(Mutex,Monitor,Interlocked和AutoResetEvent等)外,该命名空间还包含一个ThreadPool类(它允许用户使用系统提供的线程池)和一个Timer类(它在线程池的线程上执行回调方法)。


二、线程的创建和使用

Thread创建一个线程非常简单,只需要将其声明并为其提供线程起始点处的委托即可。创建新的线程时,需要使用Thread类,该类具有接受一个ThreadStart委托或ParameterizedThreadStart委托的构造函数。

2.1 ThreadStart用于无返回值,无参数的方法

public static void Main(string[] args)
{
    ThreadStart threadStart = new ThreadStart(MyThread);
    Console.WriteLine("创建一个线程");
    Thread thread= new Thread(threadStart);
    thread.Start();
}

private static void MyThread() 
{
     Console.WriteLine("This is Thread Method.");
     Thread.Sleep(2000);
     Console.WriteLine("Thread is over.....");
}

运行结果:

创建一个线程
This is Thread Method.
Thread is over.....

2.2 ParameterizedThreadStart:用于带参数的方法

public static void Main(string[] args)
{
   ParameterizedThreadStart threadStart = new ParameterizedThreadStart(MyThread);
   Console.WriteLine("创建一个线程");
   Thread thread= new Thread(threadStart);
   thread.Start(100);
}

private static void MyThread(object n) 
{
   Console.WriteLine("This is Thread Method.");
   Thread.Sleep(2000);
   Console.WriteLine("Thread is over.....");
   for (int i = 0; i <= (int)n; i += 1)
   {
      Console.WriteLine(i);
   }
}

三、线程的启动执行

线程创建后并不会理解执行,这是因为绝大多数系统不是一个实时的操作系统。在操作系统内部会实现特殊的算法进行线程之间的调度。在某个时刻它会决定当前运行哪个线程。看下面的示例:

static int id = 0;
public static void Main(string[] args)
{
   for (int i = 0; i < 10; i++)
   {
       id++;
       Thread thread = new Thread(() =>
       {
           Console.WriteLine(string.Format("{0}:{1}", Thread.CurrentThread.Name, id));
       });
       thread.Name = string.Format("Thread{0}", i);
       thread.IsBackground = true;
       thread.Start();
   }
}

执行结果:

Thread1:3
Thread0:3
Thread2:4
Thread3:5
Thread4:6
Thread5:7
Thread6:8
Thread7:9
Thread8:10
Thread9:10

使用同步参数创建线程

static int id = 0;
static void Main(string[] args)
{
   for (int i = 0; i < 5; i++, id++)
   {
       NewMethod(i, id);
   }
   Console.ReadLine();
}
private static void NewMethod(int i, int realTimeId)
{
    Thread thread = new Thread(() =>
    {
        Console.WriteLine(string.Format("{0}:{1}", Thread.CurrentThread.Name, realTimeId));
    });
    thread.Name = string.Format("Thread{0}", i);
    thread.IsBackground = true;
    thread.Start();
}

运行结果:

Thread0:0
Thread1:1
Thread2:2
Thread3:3
Thread4:4

四、线程的挂起和恢复

创建完一个线程并启动后,还可以挂起、恢复、休眠或终止线程。线程的挂起与恢复可以通过调用Thread类的Suspend方法和Resume方法实现。

4.1 Suspend方法

该方法用来挂起线程,如果线程已挂起,则不起作用。调用Suspend方法挂起线程时,.NET允许挂起的线程再执行几个指令,目的是为了到达.NET认为线程可以安全挂起的状态。

4.2 Resume方法

该方法用来继续已挂起的线程。通过Resume方法来恢复被暂停的线程时,无论调用多少次Suspend方法,调用Resume方法均会使另一个线程脱落挂起状态。

通过Resume()方法来恢复被暂停的线程时,无论调用了多少次Suspend()方法,调用Resume()方法均会使另一个线程脱离挂起状态,并导致该线程继续执行。

4.3 该方法已废弃及替代方法

Thread.Suspend()Thread.Resume()这两个方法已过时,需要使用AutoResetEventEventWaitHandle代替。


五、中止线程(About)

线程被中止,就停止运行,是无法恢复的,因为操作系统会删除被中止线程所有数据。

static void Main(string[] args)
{
     Thread myThread;                       
     myThread = new Thread(new ThreadStart(createThread));
     myThread.Start();
     myThread.Abort();
}
private static void createThread()
{
    for (long i = 0; i < 1000000000; i++)
    { 
        Console.WriteLine($"workThread-->i={i}");
    }
}

线程中止和线程挂起是一样结果,中止工作线程后,线程将不会在被执行,如果强制运行程序,将出现运行时错误。

六、线程休眠(Sleep)

使线程休眠使用Sleep()方法,此方法可以让线程休眠一定的时间,示例代码如下:

Thread workThread = new Thread(new ThreadStart(createThread));
workThread.Start();
Thread.Sleep(10000);//修改

Sleep()会让线程暂停一段时间后接着运行,休眠线程不需要手动恢复,到指定的时间后会自动执行。


七、线程等待(Join())

如果后续的处理依赖于另一个已终止的线程,可调用Join()方法,等待线程中止。

Thread workThread = new Thread(new ThreadStart(createThread));
workThread.Start();
workThread.Join();

工作线程调用了Jion()方法,需待工作线程中止后,主线程才会被执行。Jion()的其他重载方法可以指定等待的时间期限,超过了时间期限,程序会继续执行。


八、线程让步(Yield())

Yield 的中文翻译为 “屈服,让步”,这里意思是主动放弃当前线程的时间片,并让操作系统调度其它就绪态的线程使用一个时间片。但是如果调用 Yield,只是把当前线程放入到就绪队列中,而不是阻塞队列。如果没有找到其它就绪态的线程,则当前线程继续运行。Yield可以让低于当前优先级的线程得以运行,调用者可以通过返回值判断是否成功调度了其它线程。注意,Yield只能调度运行在当前CPU上的线程。


九、后台线程与前台线程

线程是后台线程或前台线程。后台线程与前台线程相同,只不过后台线程不会阻止进程终止。一旦属于进程的所有前台线程都终止,公共语言进行时将结束该进程。所有剩余的后台线程将停止,并且无法完成。

默认情况下,以下线程是前台线程:

  • 主线程(或主应用程序线程)。
  • 通过调用类构造函数创建Thread的所有线程都是前台线程。


默认情况下,以下线程在后台执行:

  • 线程池线程,由运行时维护的工作线程池。可以使用类配置线程池并计划线程池线程ThreadPool上工作。
  • 从非托管代码进入托管执行环境的所有线程。


十、Thread线程属性

  • CurrentThread:获取当前正在运行的线程。
  • IsAlive :获取指示当前线程的执行状态的值。
  • IsBackgroud:获取或设置一个值,该值指示某个线程是否为后台线程。
  • IsThreadPoolThread:获取指示线是否属于托管线程池的值。
  • Name:获取或设置线程的名称。
  • Priority:获取或设置线程调度优先级的值。
  • ThreadState:获取一个值,该值包含当前线程的状态。
目录
相关文章
|
25天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
40 5
|
3月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
101 0
|
2月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
46 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
1月前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
28 3
|
9天前
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
25 0
|
11天前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
11天前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
2月前
|
Java C# Python
线程等待(Thread Sleep)
线程等待是多线程编程中的一种同步机制,通过暂停当前线程的执行,让出CPU时间给其他线程。常用于需要程序暂停或等待其他线程完成操作的场景。不同语言中实现方式各异,如Java的`Thread.sleep(1000)`、C#的`Thread.Sleep(1000)`和Python的`time.sleep(1)`。使用时需注意避免死锁,并考虑其对程序响应性的影响。
|
2月前
|
开发框架 Java .NET
.net core 非阻塞的异步编程 及 线程调度过程
【11月更文挑战第12天】本文介绍了.NET Core中的非阻塞异步编程,包括其基本概念、实现方式及应用示例。通过`async`和`await`关键字,程序可在等待I/O操作时保持线程不被阻塞,提高性能。文章还详细说明了异步方法的基础示例、线程调度过程、延续任务机制、同步上下文的作用以及如何使用`Task.WhenAll`和`Task.WhenAny`处理多个异步任务的并发执行。
|
2月前
|
Java 网络安全 Maven
Exception in thread "main" java.lang.NoSuchMethodError: okhttp3.OkHttpClient$Builder.sslSocketFactory(Ljavax/net/ssl/SSLSocketFactory;Ljavax/net/ssl/X509TrustManager;)Lokhttp3/OkHttpClient$Builder; 问题处理
【10月更文挑战第26天】Exception in thread "main" java.lang.NoSuchMethodError: okhttp3.OkHttpClient$Builder.sslSocketFactory(Ljavax/net/ssl/SSLSocketFactory;Ljavax/net/ssl/X509TrustManager;)Lokhttp3/OkHttpClient$Builder; 问题处理
52 2