C# 多线程 ThreadStart和ParameterizedThreadStart

C# 多线程 ThreadStart和ParameterizedThreadStart线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了CPU周期的浪费,同时提高了应用程序的效率。每个线程都定义了一个独特的控制流。如果应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。线程生命周期线程生命周期开始于System.Threading.Thread类的对象被创建时,结束于线程被终止或完成执行时。线程生命周期中的各种状态:未启动状态:当线程实例被创建但Start方法未被调用时的状况。就绪状态:

大家好,又见面了,我是你们的朋友全栈君。

线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率。每个线程都定义了一个独特的控制流。如果应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。

线程生命周期

线程生命周期开始于 System.Threading.Thread 类的对象被创建时,结束于线程被终止或完成执行时。

线程生命周期中的各种状态:

  • 未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。
  • 就绪状态:当线程准备好运行并等待 CPU 周期时的状况。
  • 不可运行状态:下面的几种情况下线程是不可运行的:
    已经调用 Sleep 方法
    已经调用 Wait 方法
    通过 I/O 操作阻塞
  • 死亡状态:当线程已完成执行或已中止时的状况。

Thread 类常用的属性和方法

1、属性

属性 描述
CurrentContext 获取线程正在其中执行的当前上下文。
CurrentThread 获取当前正在运行的线程。
ExecutionContext 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
IsAlive 获取一个值,该值指示当前线程的执行状态。
IsBackground 获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread 获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId 获取当前托管线程的唯一标识符。
Name 获取或设置线程的名称。
Priority 获取或设置一个值,该值指示线程的调度优先级。
ThreadState 获取一个值,该值包含当前线程的状态。

2、方法

方法 描述
public void Abort() 在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程。
public static void ResetAbort() 取消为当前线程请求的 Abort。
public void Interrupt() 中断处于 WaitSleepJoin 线程状态的线程。
public void Join() 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。
public static Object GetData( LocalDataStoreSlot slot ) 在当前线程的当前域中从当前线程上指定的槽中检索值。
public static void SetData( LocalDataStoreSlot slot, Object data ) 在当前正在运行的线程上为此线程的当前域在指定槽中设置数据。
public void Start() 开始一个线程。
public static void Sleep( int millisecondsTimeout ) 让线程暂停一段时间。
public static void SpinWait( int iterations ) 使线程等待由 iterations 参数定义的时间量。
public static bool Yield() 调用线程执行准备好在当前处理器上运行的另一个线程。由操作系统选择要执行的线程。

实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ThreadTestConsoleApp
{ 
   
    class Program
    { 
   
        static void Main(string[] args)
        { 
   
            Thread[] newThreads = new Thread[4];
            for (int i = 0; i < newThreads.Length; i++)
            { 
   
                newThreads[i] =
                    new Thread(Slot.SlotTest);
                newThreads[i].Start();
            }
            Console.ReadKey();
        }
    }
    class Slot
    { 
   
        static Random randomGenerator = new Random();

        public static void SlotTest()
        { 
   
            Thread.SetData(
                Thread.GetNamedDataSlot("Random"),
                randomGenerator.Next(1, 200));

            Thread.Sleep(1000);

            Other o = new Other();
            o.ShowSlotData();
        }
    }

    public class Other
    { 
   
        public void ShowSlotData()
        { 
   
            Console.WriteLine("Other code displays data in thread_{0}'s data slot: {1,3}",
                AppDomain.GetCurrentThreadId().ToString(),
                Thread.GetData(
                Thread.GetNamedDataSlot("Random")).ToString());
        }
    }
}

结果:

Other code displays data in thread_{ 
   0}'s data slot: 199 Other code displays data in thread_{0}'s data slot: 119
Other code displays data in thread_{ 
   0}'s data slot: 36 Other code displays data in thread_{0}'s data slot: 98

以上实例演示了 线程的创建,睡眠以及SetData()和GetData()方法的运用。

其中newThreads[i] = new Thread(Slot.SlotTest);也可以写作:

 newThreads[i] = new Thread( new ThreadStart(Slot.SlotTest));

这两种写法的效果是一样的。都是创建一个线程。前者只是 C# 的语法,编译时编译器会自动转换成第二种的形式。ThreadStart 是线程的入口,可以理解为一个函数指针,指向线程将要运行的函数。

线程委托

1、ThreadStart
ThreadStart 是多线程的委托,所委托的方法不能有输入参数,返回值为void。

static void Main(string[] args)
{ 
   
	ThreadStart threadStart=new ThreadStart(Calculate);
	Thread thread=new Thread(threadStart);
	thread.Start();
}
public void Calculate()
{ 
   
   double Diameter=0.5;
   Console.Write("The Area Of Circle with a Diameter of {0} is {1}"Diameter,Diameter*Math.PI);
}

2、ParameterizedThreadStart
ParameterizedThreadStart的定义为void ParameterizedThreadStart(object state),使用这个委托定义的线程的启动函数可以接受一个输入参数,参数类型为object。object可以为一个类,进而达到传递多个参数的目的。
实例:

class AddParams
{ 
   
    public int a, b;

    public AddParams(int numb1, int numb2)
    { 
   
      a = numb1;
      b = numb2;
    }
}

class Program
{ 
   
    static void Main(string[] args)
    { 
   
      Console.WriteLine("***** Adding with Thread objects *****");
      Console.WriteLine("ID of thread in Main(): {0}",
        Thread.CurrentThread.ManagedThreadId);

      AddParams ap = new AddParams(10, 10);
      Thread t = new Thread(new ParameterizedThreadStart(Add));
      t.Start(ap);
      Console.ReadLine();
    }

    #region Add method
    static void Add(object data)
    { 
   
      if (data is AddParams)
      { 
   
        Console.WriteLine("ID of thread in Main(): {0}",
          Thread.CurrentThread.ManagedThreadId);

        AddParams ap = (AddParams)data;
        Console.WriteLine("{0} + {1} is {2}",
          ap.a, ap.b, ap.a + ap.b);
      }
    }
    #endregion
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/159633.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Android手机以L2TP方式连接LAVAVPN的设置方法

    Android手机以L2TP方式连接LAVAVPN的设置方法1.准备首先手机要打开WIFI或GPRS或3G连接,确保网络畅通。建议用WIFI网络测试,因为部分地区的GPRS或3G网络不支持或屏蔽VPN通讯。2.打开手机主菜单,选择"设置"3

    2022年7月2日
    36
  • Spark Streaming特点「建议收藏」

    Spark Streaming特点「建议收藏」SparkStreaming特点1、易用2、容错3、易整合到Spark体系4、SparkStreaming与Storm的对比SparkStreamingStorm开发语言:Scala开发语言:Clojure编程模型:DStream编程模型:Spout/Bolt喜欢就点赞评论…

    2022年6月24日
    31
  • js的常见的三种密码加密方式-MD5加密、Base64加密和解密和sha1加密详解总结

    js的常见的三种密码加密方式-MD5加密、Base64加密和解密和sha1加密详解总结写在前面写前端的时候,很多的时候是避免不了注册这一关的,但是一般的注册是没有任何的难度的,无非就是一些简单的获取用户输入的数据,然后进行简单的校验以后调用接口,将数据发送到后端,完成一个简单的注册的流程,那么一般来说,密码是不做加密的。但是也有一些数据库里面存放的是加密后的密码,这样有一个比较安全的地方在于,即使黑客将用户输入的文本密码得到了,也不知道具体是什么,因为密码是经过加密的。今天就简单的…

    2022年7月11日
    34
  • RC522(RFID模块)实践总结

    此次使用RC522模块和S50卡实现近场通讯功能(开发板与RC522通讯方式为硬件SPI),就实践过程中的一些知识点进行总结:RC522模块和M1卡要点介绍;驱动代码;出现问题及解决方法;1.RC522模块和M1卡要点介绍:MFRC522简化功能框图;MFRC522与主机SPI通讯引脚配置;MFRC522与M1卡的通讯原理;M1卡存储结构与指令;MFRC522简化功能框图…

    2022年4月5日
    254
  • OpenCV——Canny边缘检测(cv2.Canny())

    OpenCV——Canny边缘检测(cv2.Canny())Canny边缘检测Canny边缘检测是一种使用多级边缘检测算法检测边缘的方法。1986年,JohnF.Canny发表了著名的论文AComputationalApproachtoEdgeDetection,在该论文中详述了如何进行边缘检测。Canny()边缘检测步骤Canny边缘检测分为如下几个步骤:步骤1:去噪。噪声会影响边缘检测的准确性,因此首先要将噪声过滤掉。步骤2:计算梯度的幅度与方向。步骤3:非极大值抑制,即适当地让边缘“变瘦”。步骤4:确定边缘。使

    2022年5月25日
    44
  • Hibernate框架–学习笔记(下):hibernate的查询方式、多表查询、检索策略、批量抓取

    Hibernate框架–学习笔记(下):hibernate的查询方式、多表查询、检索策略、批量抓取

    2021年9月26日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号