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日

相关文章

  • Ant Design Blazor 组件库的路由复用多标签页功能

    Ant Design Blazor 组件库的路由复用多标签页功能可以在实际开发中提高用户交互效率,具有较高的实用价值。下面,我将详细讲解如何实现该功能的完整攻略。 1. 环境准备 在使用 Ant Design Blazor 组件库实现路由复用多标签页功能前,我们需要先准备好以下环境: Visual Studio 2019 或以上版本 .NET 5.0 或以上…

    C# 2023年6月3日
    00
  • 简单聊聊c# 事件

    好的。首先,我将介绍C#中的事件。事件是一种声明,当特定动作发生时,事件会在代码中触发。例如,可以在单击按钮时触发单击事件,或者在完全加载页面时触发加载事件。在事件被触发时,可以调用与事件相关的代码,以提供所需的功能。 在C#中,我们可以通过声明delegate类型来定义事件。delegate类型是一种数据类型,它引用一个方法,该方法可以用于处理事件的调用。…

    C# 2023年6月1日
    00
  • ASP.NET笔记之 Httphandler的操作详解

    ASP.NET笔记之 Httphandler的操作详解。 什么是Httphandler? Httphandler(处理程序)是ASP.NET处理请求的一个模块,可以实现自定义的请求处理逻辑。Httphandler是ASP.NET MVC中请求和响应的核心组件之一,它可以拦截请求并对其进行某些操作,比如从数据库中读取数据然后呈现在页面上。 创建和注册Httph…

    C# 2023年6月3日
    00
  • asp.net 用户控件读取以及赋值

    让我们来详细讲解一下如何读取和赋值 ASP.NET 用户控件。 什么是 ASP.NET 用户控件? ASP.NET 用户控件是由 ASP.NET 页面和服务器控件组成的。它们是可重用的模块,可以在多个页面中使用,并且可以像其他服务器控件一样自定义和配置。用户控件通常用于在多个页面中使用相同的用户界面元素。 如何创建 ASP.NET 用户控件? 要创建 ASP…

    C# 2023年6月3日
    00
  • C#枚举类型和结构体详解

    C#枚举类型和结构体详解 枚举类型 C#中的枚举类型是一种特殊的数据类型,用于定义常量。它可以帮助我们在程序中使用更加直观的符号来代表特定的整数值。枚举类型的定义语法如下: enum 枚举名称 { 常量1, 常量2, … } 其中,枚举名称是标识枚举类型的名称,常量1、常量2等是枚举类型中定义的常量,可以指定特定的值,也可以不指定,如果不指定,则默认从0…

    C# 2023年6月8日
    00
  • C#使用iCSharpcode进行文件压缩实现方法

    下面是“C#使用iCSharpcode进行文件压缩实现方法”的完整攻略。 1. 引入iCSharpcode.SharpZipLib库 在C#中使用iCSharpcode进行文件压缩需要引入其提供的SharpZipLib库。可以通过NuGet来引入,也可以直接下载安装至本地项目中。 2. 使用ZipOutputStream进行文件压缩 压缩一个文件可以使用如下…

    C# 2023年6月1日
    00
  • ASP.NET如何自定义项目模板详解

    ASP.NET如何自定义项目模板详解 ASP.NET是一个动态站点开发工具,它可以帮助开发者快速构建Web应用程序。ASP.NET允许开发者自定义项目模板,以便在日常开发中提高工作效率。本文将介绍如何自定义ASP.NET项目模板,以及如何使用自定义项目模板。 1. 创建自定义项目模板 步骤如下: 在Visual Studio中创建一个新的ASP.NET项目。…

    C# 2023年6月3日
    00
  • C# Mysql 查询 Rownum的解决方法

    下面就给你详细讲解C#和Mysql查询Rownum的解决方法。 什么是Rownum Rownum是Oracle数据库中的一个概念,用于获取指定条件下的前N条记录,但是在Mysql中并没有Rownum,可以通过一些技巧模拟出来。 解决方法 方法一:使用变量模拟Rownum 通过定义一个变量,然后根据变量的值来返回前N条结果。 SET @num := 0, @r…

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