C#的线程

2024-10-09 22:03:24 浏览数 (2)

多线程编程是现代软件开发中的一项关键技术,它允许程序同时执行多个任务,从而提高应用程序的响应性和性能。C#提供了丰富的线程管理功能,包括线程的创建、同步、通信和池化等。本文将深入探讨C#中线程的工作原理、使用场景、最佳实践以及一些高级技巧。

线程的基本概念

在C#中,线程是操作系统中最小的执行单元,是程序执行的最小单位。每个线程都有自己的调用栈和状态信息。

主线程与后台线程

  • 主线程:程序运行的主要线程,通常用于UI交互。
  • 后台线程:用于执行后台任务,不会阻止程序退出。

线程的生命周期

线程的生命周期包括新建、就绪、运行、挂起、恢复和终止等状态。

核心API

Thread

Thread类是C#中最基本的线程管理类,提供了创建和控制线程的方法。

ThreadPool

ThreadPool是一个线程池,用于管理和复用线程,以提高资源利用率和性能。

Task

Task是.NET中用于表示异步操作的类,它基于线程池来执行。

MutexSemaphoreMonitor

这些类用于线程同步,防止多个线程同时访问共享资源。

创建和启动线程

使用Thread

代码语言:javascript复制
using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Thread newThread = new Thread(() => Console.WriteLine("Hello from a new thread!"));
        newThread.Start();
        Console.WriteLine("Hello from the main thread!");
    }
}

使用ThreadPool

代码语言:javascript复制
using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        ThreadPool.QueueUserWorkItem(state =>
        {
            Console.WriteLine("Hello from ThreadPool thread!");
        });
        Console.WriteLine("Hello from the main thread!");
    }
}

使用Task

代码语言:javascript复制
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Task myTask = Task.Run(() =>
        {
            Console.WriteLine("Hello from a Task!");
        });
        await myTask;
        Console.WriteLine("Hello from the main thread!");
    }
}

线程同步

使用lock关键字

代码语言:javascript复制
using System;
using System.Threading;

class Program
{
    private static readonly object lockObject = new object();
    private static int sharedResource = 0;

    static void Main(string[] args)
    {
        Thread thread1 = new Thread(Increment);
        Thread thread2 = new Thread Increment);

        thread1.Start();
        thread2.Start();

        thread1.Join();
        thread2.Join();

        Console.WriteLine($"Shared resource value: {sharedResource}");
    }

    static void Increment()
    {
        lock(lockObject)
        {
            for (int i = 0; i < 1000000; i  )
            {
                sharedResource  ;
            }
        }
    }
}

使用Mutex

代码语言:javascript复制
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        Mutex mutex = new Mutex();
        Task task1 = Task.Run(() =>
        {
            mutex.WaitOne();
            try
            {
                Console.WriteLine("Task 1 is executing.");
                Thread.Sleep(2000);
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        });

        Task task2 = Task.Run(() =>
        {
            mutex.WaitOne();
            try
            {
                Console.WriteLine("Task 2 is executing.");
                Thread.Sleep(2000);
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        });

        Task.WhenAll(task1, task2).Wait();
    }
}

使用Semaphore

代码语言:javascript复制
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        Semaphore semaphore = new Semaphore(1, 1);
        Task task1 = Task.Run(() =>
        {
            semaphore.WaitOne();
            try
            {
                Console.WriteLine("Task 1 is executing.");
                Thread.Sleep(2000);
            }
            finally
            {
                semaphore.Release();
            }
        });

        Task task2 = Task.Run(() =>
        {
            semaphore.WaitOne();
            try
            {
                Console.WriteLine("Task 2 is executing.");
                Thread.Sleep(2000);
            }
            finally
            {
                semaphore.Release();
            }
        });

        Task.WhenAll(task1, task2).Wait();
    }
}

使用Monitor

代码语言:javascript复制
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    private static object lockObject = new object();
    private static int sharedResource = 0;

    static void Main(string[] args)
    {
        Task task1 = Task.Run(() =>
        {
            for (int i = 0; i < 1000000; i  )
            {
                Monitor.Enter(lockObject);
                try
                {
                    sharedResource  ;
                }
                finally
                {
                    Monitor.Exit(lockObject);
                }
            }
        });

        Task task2 = Task.Run(() =>
        {
            for (int i = 0; i < 1000000; i  )
            {
                Monitor.Enter(lockObject);
                try
                {
                    sharedResource  ;
                }
                finally
                {
                    Monitor.Exit(lockObject);
                }
            }
        });

        Task.WhenAll(task1, task2).Wait();

        Console.WriteLine($"Shared resource value: {sharedResource}");
    }
}

线程间通信

使用AutoResetEventManualResetEvent

代码语言:javascript复制
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static AutoResetEvent autoResetEvent = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        Task producerTask = Task.Run(() =>
        {
            for (int i = 0; i < 5; i  )
            {
                Console.WriteLine($"Produced: {i}");
                autoResetEvent.Set();
                Thread.Sleep(1000); // Simulate work
            }
        });

        Task consumerTask = Task.Run(() =>
        {
            for (int i = 0; i < 5; i  )
            {
                autoResetEvent.WaitOne();
                Console.WriteLine($"Consumed: {i}");
            }
        });

        Task.WhenAll(producerTask, consumerTask).Wait();
    }
}

使用BlockingCollection

代码语言:javascript复制
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        BlockingCollection<int> collection = new BlockingCollection<int>(new ConcurrentQueue<int>(), 10);
        CancellationTokenSource cts = new CancellationTokenSource();

        Task producerTask = Task.Run(() =>
        {
            for (int i = 0; i < 20; i  )
            {
                collection.Add(i);
                Console.WriteLine($"Produced: {i}");
                Thread.Sleep(1000); // Simulate work
            }
            cts.Cancel();
        });

        Task consumerTask = Task.Run(() =>
        {
            try
            {
                foreach (int item in collection.GetConsumingEnumerable(cts.Token))
                {
                    Console.WriteLine($"Consumed: {item}");
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Consuming cancelled.");
            }
        });

        Task.WhenAll(producerTask, consumerTask).Wait();
    }
}

高级技巧

线程局部存储

使用ThreadLocal<T>来存储线程特定的数据。

代码语言:javascript复制
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static ThreadLocal<int> localData = new ThreadLocal<int>(() => 0);

    static void Main(string[] args)
    {
        Task task1 = Task.Run(() =>
        {
            localData.Value = 1;
            Console.WriteLine($"Task 1 local data: {localData.Value}");
        });

        Task task2 = Task.Run(() =>
        {
            localData.Value = 2;
            Console.WriteLine($"Task 2 local data: {localData.Value}");
        });

        Task.WhenAll(task1, task2).Wait();
    }
}

参数化线程

在创建线程时传递参数。

代码语言:javascript复制
using System;
using System.Threading;

class Program
{
    static void ThreadMethod(object o)
    {
        Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} says: {o}");
    }

    static void Main(string[] args)
    {
        Thread newThread = new Thread(new ParameterizedThreadStart(ThreadMethod));
        newThread.Start("Hello from a thread!");
        Console.WriteLine($"Main thread says: {o}");
    }
}

定时器线程

使用Timer类来周期性地执行任务

代码语言:javascript复制
using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Timer timer = new Timer(TimerCallback, null, 0, 1000);
        Console.WriteLine("Press enter to exit...");
        Console.ReadLine();
    }

    private static void TimerCallback(object state)
    {
        Console.WriteLine("Timer callback executed!");
    }
}

异步局部变量

使用AsyncLocal<T>来存储异步上下文中的数据。

代码语言:javascript复制
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static AsyncLocal<int> localData = new AsyncLocal<int>();

    static void Main(string[] args)
    {
        localData.Value = 1;

        Task task1 = Task.Run(async () =>
        {
            await Task.Delay(1000);
            Console.WriteLine($"Task 1 local data: {localData.Value}");
        });

        Task task2 = Task.Run(async () =>
        {
            await Task.Delay(1000);
            Console.WriteLine($"Task 2 local data: {localData.Value}");
        });

        Task.WhenAll(task1, task2).Wait();
    }
}

性能优化

避免过度线程化

创建线程是有成本的,过多的线程会导致上下文切换和资源竞争。

使用线程池

使用线程池可以减少线程创建和销毁的开销。

优化锁的使用

尽量减少锁的使用范围和持有时间,使用读写锁来优化读多写少的场景。

减少线程同步

使用无锁编程技术,如Interlocked类,来减少线程同步的开销。

0 人点赞