C# 多线程 ThreadStart和ParameterizedThreadStart

线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了 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
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#中,可以使用Thread类来创建多个线程,并通过调用方法来启动这些线程。如果要在多线程中调用带参数有返回值的方法,可以使用委托和异步回调来实现。下面是一个简单的示例代码,演示如何创建和启动多个线程来调用同一个带参数有返回值的方法: ```csharp using System; using System.Threading; class Program { static void Main(string[] args) { // 创建3个线程 Thread t1 = new Thread(new ParameterizedThreadStart(MyMethod)); Thread t2 = new Thread(new ParameterizedThreadStart(MyMethod)); Thread t3 = new Thread(new ParameterizedThreadStart(MyMethod)); // 启动这些线程 t1.Start(1); t2.Start(2); t3.Start(3); // 等待这些线程结束 t1.Join(); t2.Join(); t3.Join(); Console.WriteLine("所有线程已结束"); } static void MyMethod(object param) { int num = (int)param; // 这里是你要执行的方法 Console.WriteLine("线程 {0} 正在执行 MyMethod,参数为 {1}", Thread.CurrentThread.ManagedThreadId, num); // 模拟方法执行 Thread.Sleep(1000); // 返回结果 int result = num * 2; // 调用回调函数返回结果 AsyncCallback callback = new AsyncCallback(MyCallback); callback.BeginInvoke(result, null, null); } static void MyCallback(IAsyncResult result) { int num = (int)result.AsyncState; Console.WriteLine("线程 {0} 的 MyMethod 方法返回了结果 {1}", Thread.CurrentThread.ManagedThreadId, num); } } ``` 在这个示例中,我们创建了3个线程,并通过调用Thread.Start()方法来启动它们。这些线程都会调用同一个方法MyMethod(),并传入一个整数参数。在MyMethod()方法中,我们模拟了方法的执行过程,并最终返回了一个整数结果。为了返回结果,我们使用了异步回调的方式,将结果传递给MyCallback()方法进行处理。在MyCallback()方法中,我们输出了方法执行的结果。 需要注意的是,多线程编程需要注意线程安全性,以免出现竞态条件等问题。在实际开发中,需要根据具体情况来选择适合的多线程编程模型和技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值