📜  .net core 中的多线程 - C# (1)

📅  最后修改于: 2023-12-03 15:13:04.012000             🧑  作者: Mango

.NET Core 中的多线程 - C#

在 .NET Core 中,我们可以使用多线程来提高程序的性能和响应能力。在本文中,我们将介绍如何在 C# 中使用多线程及其相关概念和技术。

线程和进程

在计算机系统中,进程是指一个正在运行的程序,而线程是指进程中的一个执行单元。每个线程都拥有自己的执行环境,包括栈、寄存器等等。一个进程可以包含多个线程,这些线程可以共享进程的资源,如内存、文件句柄等等。

创建线程

在 C# 中,我们可以使用 Thread 类来创建线程。以下是创建线程的几个步骤:

  1. 创建一个委托,该委托表示线程要执行的方法。
  2. 创建一个 Thread 实例,并将该委托传递给它的构造函数。
  3. 调用 Thread 实例的 Start 方法,启动线程。

以下是一个简单的示例:

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Thread thread = new Thread(DoWork);
        thread.Start();
        Console.WriteLine("Main thread: The worker thread has started.");
    }

    static void DoWork()
    {
        Console.WriteLine("Worker thread: Job started.");
        Thread.Sleep(5000); // 模拟工作
        Console.WriteLine("Worker thread: Job completed.");
    }
}

在上面的示例中,我们创建了一个 DoWork 方法,该方法模拟了一些工作。然后,我们创建一个线程,并将 DoWork 方法作为参数传递给线程的构造函数。最后,我们调用 Start 方法来启动线程。

请注意,当我们运行这个程序时,我们可以看到 "Main thread: The worker thread has started." 这行文本是在工作线程(DoWork 方法)开始执行之前输出的。

线程同步

当多个线程同时访问共享资源时,就会出现问题。这时就需要使用线程同步来协调各个线程之间的访问。以下是一些常见的线程同步技术:

互斥锁

互斥锁是一种用于线程同步的机制,它可以确保同时只有一个线程可以访问共享资源。以下是一个互斥锁的示例:

using System;
using System.Threading;

class Program
{
    static object lockObject = new object();

    static void Main(string[] args)
    {
        Thread thread1 = new Thread(DoWork);
        Thread thread2 = new Thread(DoWork);
        thread1.Start();
        thread2.Start();
    }

    static void DoWork()
    {
        lock (lockObject)
        {
            Console.WriteLine("Thread {0}: Job started.", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(5000); // 模拟工作
            Console.WriteLine("Thread {0}: Job completed.", Thread.CurrentThread.ManagedThreadId);
        }
    }
}

在上面的示例中,我们使用了一个名为 lockObject 的对象来作为互斥锁。在 DoWork 方法中,我们使用 lock 语句来锁住这个对象。这样,当一个线程正在使用共享资源时,另一个线程将不能进入这个锁定代码块,直到第一个线程完成工作并释放锁。

Semaphore

Semaphore 是一种线程同步的机制,它可以控制同时访问共享资源的线程数量。以下是一个 Semaphore 的示例:

using System;
using System.Threading;

class Program
{
    static Semaphore semaphore = new Semaphore(2, 2); // 限制为 2 个同时执行的线程

    static void Main(string[] args)
    {
        Thread thread1 = new Thread(DoWork);
        Thread thread2 = new Thread(DoWork);
        Thread thread3 = new Thread(DoWork);
        thread1.Start();
        thread2.Start();
        thread3.Start();
    }

    static void DoWork()
    {
        semaphore.WaitOne(); // 请求一个信号量
        Console.WriteLine("Thread {0}: Job started.", Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(5000); // 模拟工作
        Console.WriteLine("Thread {0}: Job completed.", Thread.CurrentThread.ManagedThreadId);
        semaphore.Release(); // 释放一个信号量
    }
}

在上面的示例中,我们创建了一个 Semaphore,它最多可以同时有两个线程在执行。在 DoWork 方法中,我们使用 WaitOne 语句来请求一个信号量,这会使信号量的计数器减少 1。而在方法结束时,我们使用 Release 语句来释放一个信号量,这会使信号量的计数器增加 1。

线程池

线程池是一种可以通过重用现有线程来减少线程创建和销毁次数的技术。在 .NET Core 中,我们可以使用 ThreadPool 类来创建和管理线程池中的线程。

以下是一个使用线程池的示例:

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 10; i++)
        {
            ThreadPool.QueueUserWorkItem(DoWork, i); // 将工作项添加到线程池队列中
        }
        Console.ReadLine();
    }

    static void DoWork(object state)
    {
        int workIndex = (int)state;
        Console.WriteLine("Thread {0}: Job {1} started.", Thread.CurrentThread.ManagedThreadId, workIndex);
        Thread.Sleep(5000); // 模拟工作
        Console.WriteLine("Thread {0}: Job {1} completed.", Thread.CurrentThread.ManagedThreadId, workIndex);
    }
}

在上面的示例中,我们通过循环将 10 个工作项添加到线程池队列中。每个工作项都是一个对象,可以携带一些信息。在 DoWork 方法中,我们可以通过 state 参数来获取这些信息。

总结

在 .NET Core 中,我们可以使用多线程来提高程序的性能和响应能力。我们可以使用 Thread 类来创建线程,并使用互斥锁、Semaphore 等机制来进行线程同步。另外,在 C# 中,我们还可以使用线程池来优化线程的创建和销毁过程。