C#多线程学习(二) 如何操纵一个线程

C#多线程学习(二) 如何操纵一个线程

下面我们就动手来创建一个线程,使用Thread类创建线程时,只需提供线程入口即可。(线程入口使程序知道该让这个线程干什么事)

在C#中,线程入口是通过ThreadStart代理(delegate)来提供的,你可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,当调用Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数。打开你的VS.net,新建一个控制台应用程序(Console Application),编写完全控制一个线程的代码示例:

//ThreadTest.cs
using System;
using System.Threading;
namespace ThreadTest
{
    public class Alpha
    {
        public void Beta()
        {
            while (true)
            {
                Console.WriteLine("Alpha.Beta is running in its own thread.");
            }
        }
    };
    public class Simple
    {
        public static int Main()
        {
            Console.WriteLine("Thread Start/Stop/Join Sample");
            Alpha oAlpha = new Alpha();
            file://这里创建一个线程,使之执行Alpha类的Beta()方法
            Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
            oThread.Start();
            while (!oThread.IsAlive)
                Thread.Sleep(1);
            oThread.Abort();
            oThread.Join();
            Console.WriteLine();
            Console.WriteLine("Alpha.Beta has finished");
            try
            {
                Console.WriteLine("Try to restart the Alpha.Beta thread");
                oThread.Start();
            }
            catch (ThreadStateException)
            {
                Console.Write("ThreadStateException trying to restart Alpha.Beta.");
                Console.WriteLine("Expected since aborted threads cannot be restarted.");
                Console.ReadLine();
            }
            return 0;
        }
    }
}

这段程序包含两个类Alpha和Simple,在创建线程oThread时我们用指向Alpha.Beta()方法的初始化了ThreadStart代理(delegate)对象,当我们创建的线程oThread调用oThread.Start()方法启动时,实际上程序运行的是Alpha.Beta()方法:

Alpha oAlpha = new Alpha();
Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
oThread.Start();

然后在Main()函数的while循环中,我们使用静态方法Thread.Sleep()让主线程停了1ms,这段时间CPU转向执行线程oThread。然后我们试图用Thread.Abort()方法终止线程oThread,注意后面的oThread.Join(),Thread.Join()方法使主线程等待,直到oThread线程结束。你可以给Thread.Join()方法指定一个int型的参数作为等待的最长时间。之后,我们试图用Thread.Start()方法重新启动线程oThread,但是显然Abort()方法带来的后果是不可恢复的终止线程,所以最后程序会抛出ThreadStateException异常。

主线程Main()函数

所有线程都是依附于Main()函数所在的线程的,Main()函数是C#程序的入口,起始线程可以称之为主线程。
如果所有的前台线程都停止了,那么主线程可以终止,而所有的后台线程都将无条件终止。
所有的线程虽然在微观上是串行执行的,但是在宏观上你完全可以认为它们在并行执行。

Thread.ThreadState 属性

这个属性代表了线程运行时状态,在不同的情况下有不同的值,我们有时候可以通过对该值的判断来设计程序流程。
ThreadState 属性的取值如下:
Aborted:线程已停止;
AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止;
Background:线程在后台执行,与属性Thread.IsBackground有关;
Running:线程正在正常运行;
Stopped:线程已经被停止;
StopRequested:线程正在被要求停止;
Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行);
SuspendRequested:线程正在要求被挂起,但是未来得及响应;
Unstarted:未调用Thread.Start()开始线程的运行;
WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;

上面提到了Background状态表示该线程在后台运行,那么后台运行的线程有什么特别的地方呢?其实后台线程跟前台线程只有一个区别,那就是后台线程不妨碍程序的终止。一旦一个进程所有的前台线程都终止后,CLR(通用语言运行环境)将通过调用任意一个存活中的后台进程的Abort()方法来彻底终止进程。

线程的优先级

当线程之间争夺CPU时间时,CPU 是按照线程的优先级给予服务的。在C#应用程序中,用户可以设定 5 个不同的优先级,由高到低分别是Highest,AboveNormal,Normal,BelowNormal,Lowest,在创建线程时如果不指定优先级,那么系统默认为ThreadPriority.Normal。

给一个线程指定优先级,我们可以使用如下代码:

//设定优先级为最低
myThread.Priority = ThreadPriority.Lowest;

通过设定线程的优先级,我们可以安排一些相对重要的线程优先执行,例如对用户的响应等等。

原文链接:https://www.cnblogs.com/x-zhi/archive/2023/04/19/17331958.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#多线程学习(二) 如何操纵一个线程 - Python技术站

(0)
上一篇 2023年4月19日
下一篇 2023年4月19日

相关文章

  • async/await地狱该如何避免详解

    当使用异步操作的时候,我们通常会用到async/await来处理异步请求,但是如果不恰当地使用,可能会出现“async/await地狱”的情况,导致代码难以维护和阅读。以下是一些可以避免“async/await地狱”的技巧: 1. 使用Promise.all来并发执行多个异步操作 如果需要执行多个异步操作,可以考虑使用Promise.all来并发执行它们。使…

    C# 2023年6月6日
    00
  • .net基础收集汇总

    对于网站中关于“.net基础收集汇总”的完整攻略,这里给出详细的讲解: 一、攻略简介 该攻略主要包含以下方面的内容: .NET基础知识介绍 .NET常见问题解答 .NET编程工具与环境介绍 .NET学习资源推荐 其中,”.NET基础知识介绍”是该攻略的重点部分,将详细介绍.NET平台的概述、语言基础、类库常用类型、多线程编程等重要知识点。 二、攻略详情 1.…

    C# 2023年6月6日
    00
  • C#中的图像Image类与打印Printing类用法

    C#中的图像Image类与打印Printing类用法攻略 概述 在C#中,Image类和Printing类都是常用的操作图像和打印的类,它们提供了丰富的方法和属性,可以方便地实现各种图像的处理和打印。 Image类:Image类是用于操作图像的类,可以将图像加载到内存中、进行绘制、剪切等操作。 Printing类:Printing类是用于打印的类,可以控制打…

    C# 2023年6月8日
    00
  • 详解java中import的作用

    在Java中,import关键字用于导入其他类或接口的定义,以便在当前类中使用。本文将详细介绍Java中import的作用,包括import的语法、使用方法和注意事项等。 import的语法 在Java中,import关键字的语法如下: import package.name.ClassName; 其中,package.name是要导入的类或接口所在的包名,…

    C# 2023年5月15日
    00
  • c# WPF中的TreeView使用详解

    下面我将详细讲解“c# WPF中的TreeView使用详解”的完整攻略。该攻略将从以下几个方面进行讲解: 简介与基础概念 常用属性与方法的介绍 实战示例 简介与基础概念 TreeView是WPF中用于显示树结构的控件,常用于显示文件夹、目录等具有层级结构的数据。TreeView由节点和分支构成,每个节点可以包含零个或多个子节点,分支表示父子关系。 在Tree…

    C# 2023年5月31日
    00
  • C#中如何使用redis

    下面是使用C#连接Redis的完整攻略: 准备工作 在开始使用C#连接Redis之前,需要确保机器上已经安装了Redis。如果没有安装Redis,可以从https://redis.io/download这个官网下载Redis并安装。 安装完成后,需要启动Redis服务,可以通过命令行输入 redis-server 来启动Redis服务。 在C#中连接Redi…

    C# 2023年6月6日
    00
  • C# websocket及时通信协议的实现方法示例

    下面我们详细讲解“C# WebSocket及时通信协议的实现方法示例”的完整攻略。 1. WebSocket 协议介绍 WebSocket 协议是一种在单个 TCP 连接上进行全双工通信的协议,它可以在客户端和服务器之间建立持久性的连接,以支持双向实时消息传递。它可以通过 HTTP/1.1 中的 Upgrade 头字段和 Connection 头字段来进行开…

    C# 2023年6月7日
    00
  • .NET 6开发TodoList应用之使用AutoMapper实现GET请求

    一、前言 本文将会详细讲解如何使用AutoMapper实现GET请求。在本文中,我们将会使用.NET 6和AutoMapper来搭建一个TodoList应用程序,以便我们更好的理解AutoMapper的作用。 二、什么是AutoMapper AutoMapper是一个.NET的对象映射库。它的作用是将一个对象类型的数据转换为另一个对象类型的数据。因为在实际项…

    C# 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部