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用于等待所有下载任务完成,并收集每个任务的结果。

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

相关推荐
jerry60911 分钟前
c++流对象
开发语言·c++·算法
fmdpenny12 分钟前
用python写一个相机选型的简易程序
开发语言·python·数码相机
虾球xz16 分钟前
游戏引擎学习第247天:简化DEBUG_VALUE
c++·学习·游戏引擎
海盗强1 小时前
Babel、core-js、Loader之间的关系和作用全解析
开发语言·前端·javascript
猿榜编程1 小时前
python基础-requests结合AI实现自动化数据抓取
开发语言·python·自动化
我最厉害。,。1 小时前
PHP 反序列化&原生类 TIPS&字符串逃逸&CVE 绕过漏洞&属性类型特征
android·开发语言·php
爱编程的鱼1 小时前
C# 类(Class)教程
开发语言·c#
2301_817031651 小时前
C语言-- 深入理解指针(4)
c语言·开发语言·算法
superior tigre1 小时前
C++学习:六个月从基础到就业——模板编程:模板特化
开发语言·c++·学习
·醉挽清风·2 小时前
学习笔记—双指针算法—移动零
c++·笔记·学习·算法