C#学习第19天:多线程

什么是多线程?


  • 定义:多线程允许一个程序分成多个独立的执行路径来进行并发操作。
  • 用途:提高程序的执行效率,特别是在I/O操作、计算密集型任务和用户交互中。

多线程核心概念


1. 创建和管理线程

  • 使用 Thread 类
cs 复制代码
using System;
using System.Threading;

public class Program
{
    public static void Main()
    {
        Thread thread = new Thread(new ThreadStart(DoWork));
        thread.Start();

        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("Main thread: " + i);
            Thread.Sleep(100);
        }

        thread.Join(); // 等待新线程完成
    }

    public static void DoWork()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("Worker thread: " + i);
            Thread.Sleep(100);
        }
    }
}

2. 线程池

  • 使用 ThreadPool 线程池可以有效地管理和复用线程资源。
cs 复制代码
using System;
using System.Threading;

public class Program
{
    public static void Main()
    {
        ThreadPool.QueueUserWorkItem(DoWork);

        Console.WriteLine("Main thread does some work, then sleeps.");
        Thread.Sleep(1000);
        Console.WriteLine("Main thread exits.");
    }

    public static void DoWork(object state)
    {
        Console.WriteLine("Worker thread is processing the task.");
    }
}

3. 使用任务并行库 (TPL)

  • 使用 Task 和 Task<T> 任务并行库提供了更高层次的抽象来处理异步编程。
cs 复制代码
using System;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        Task workTask = DoWorkAsync();
        Console.WriteLine("Main thread continues to run.");

        await workTask; // 等待异步任务完成
    }

    public static async Task DoWorkAsync()
    {
        await Task.Delay(1000); // 模拟异步工作
        Console.WriteLine("Async task has completed.");
    }
}

高级主题


线程间同步

  • 使用锁 (lock) 防止数据竞争
cs 复制代码
public class Counter
{
    private int count = 0;
    private readonly object lockObj = new object();

    public void Increment()
    {
        lock (lockObj)
        {
            count++;
        }
    }
}

并发集合

  • .NET提供了一些线程安全的集合类,如ConcurrentDictionary、BlockingCollection等。
cs 复制代码
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

public class ConcurrentExample
{
    public static void Main()
    {
        var concurrentBag = new ConcurrentBag<int>();

        Parallel.For(0, 10, i =>
        {
            concurrentBag.Add(i);
        });

        foreach (var item in concurrentBag)
        {
            Console.WriteLine(item);
        }
    }
}

使用场景


1.I/O密集型操作:

  • 多线程可以提高文件读写或网络请求的吞吐量。

2.后台任务:

  • 在不影响主线程响应的情况下执行长时间运行的计算或更新。

3.用户界面:

  • 使用多线程可防止UI卡顿,保持应用程序响应性。

实践习题


cs 复制代码
using System;
using System.Threading;

public class Program
{
    private static readonly object lockObj = new object();
    private static int counter = 0;
    private const int maxCount = 10;

    public static void Main()
    {
        Thread evenThread = new Thread(PrintEven);
        Thread oddThread = new Thread(PrintOdd);

        evenThread.Start();
        oddThread.Start();

        evenThread.Join();
        oddThread.Join();
    }

    public static void PrintEven()
    {
        while (true)
        {
            lock (lockObj)
            {
                if (counter >= maxCount)
                    break;

                if (counter % 2 == 0)
                {
                    Console.WriteLine("Even: " + counter);
                    counter++;
                }
            }
        }
    }

    public static void PrintOdd()
    {
        while (true)
        {
            lock (lockObj)
            {
                if (counter >= maxCount)
                    break;

                if (counter % 2 != 0)
                {
                    Console.WriteLine("Odd: " + counter);
                    counter++;
                }
            }
        }
    }
}

说明:

  • 使用一个公共的整数counter来记录当前数字。
  • 两个线程PrintEven和PrintOdd分别负责打印偶数和奇数。
  • 使用lock关键字确保对counter的访问是线程安全的。

2.实现一个程序,通过Task启动多个异步下载模拟任务,并在全部完成后输出结果。

cs 复制代码
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        List<Task<string>> downloadTasks = new List<Task<string>>();

        // 模拟三个下载任务
        downloadTasks.Add(SimulateDownloadAsync("File1"));
        downloadTasks.Add(SimulateDownloadAsync("File2"));
        downloadTasks.Add(SimulateDownloadAsync("File3"));

        string[] results = await Task.WhenAll(downloadTasks);

        foreach (string result in results)
        {
            Console.WriteLine(result);
        }
    }

    public static async Task<string> SimulateDownloadAsync(string fileName)
    {
        // 模拟下载延迟
        await Task.Delay(new Random().Next(500, 2000));
        return $"{fileName} downloaded.";
    }
}

说明:

  • 使用Task启动多个异步下载任务。
  • SimulateDownloadAsync方法模拟下载过程,返回任务完成后的消息。
  • Task.WhenAll用于等待所有下载任务完成,并收集每个任务的结果。

这些例子展示了如何使用多线程和任务并行库来管理并发操作,提高程序效率。如果有任何问题或需要进一步讲解,请随时告诉我!

相关推荐
freyazzr8 分钟前
TCP/IP 网络编程 | Reactor事件处理模式
开发语言·网络·c++·网络协议·tcp/ip
电院工程师16 分钟前
SM3算法Python实现(无第三方库)
开发语言·python·算法·安全·密码学
爱意随风起风止意难平23 分钟前
如何用AI赋能学习
人工智能·学习·aigc
YuTaoShao23 分钟前
Java八股文——MySQL「存储引擎篇」
java·开发语言·mysql
AI风老师25 分钟前
通信网络基础概念
开发语言·网络·php
王德博客34 分钟前
【Java课堂笔记】Java 入门基础语法与面向对象三大特性详解
java·开发语言
wkj0011 小时前
接口实现类向上转型和向上转型解析
java·开发语言·c#
viperrrrrrrrrr71 小时前
大数据学习(137)-大数据组件运行时角色
大数据·hive·学习·flink·spark
月白风清江有声1 小时前
lsprepost岩石爆炸仿真——学习札记2
学习
寒士obj1 小时前
类加载的过程
java·开发语言