首页 > 编程语言 >C#异步和多线程的理解

C#异步和多线程的理解

时间:2024-11-06 09:22:29浏览次数:1  
标签:异步 Task C# 任务 线程 多线程 CPU

1. 异步编程(Asynchronous Programming)

异步编程是通过非阻塞方式执行任务,通常适用于I/O 密集型任务,例如文件读写、网络请求、数据库访问等。这类操作不需要占用大量 CPU 资源,而是等待外部资源(如网络或硬盘)响应。

在 C# 中,异步编程使用 asyncawait 关键字来实现。异步方法会返回 TaskTask<T>,调用 await 后,主线程可以继续执行其他代码,不会被阻塞。异步任务完成后,程序会回到 await 的位置继续执行。

异步代码示例

以下是一个使用异步编程的示例:

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        Console.WriteLine("Starting download...");
        string content = await DownloadContentAsync("https://example.com");
        Console.WriteLine("Download completed!");
        Console.WriteLine($"Content length: {content.Length}");
    }

    static async Task<string> DownloadContentAsync(string url)
    {
        using HttpClient client = new HttpClient();
        // 异步地开始下载内容
        string content = await client.GetStringAsync(url);
        return content;
    }
}

在这个例子中,DownloadContentAsync 是一个异步方法。调用 await DownloadContentAsync(...) 后,Main 方法不会被阻塞,它会释放 CPU,等到下载完成后再继续执行。这种非阻塞模式适合 I/O 密集型任务。
这里该怎么理解,为什么不会阻塞,举个实际业务的例子,就是微信支付的接口并不马上返回支付结果,这就是没有阻塞线程,线程继续做其他事情,支付结果通过回调接口通知;那么如果不是异步会是什么样的,那就是一直等待微信支付的接口响应,这个时候线程就被阻塞了。异步可以理解成回调,进一步说.Net程序向操作系统读取文件,访问网络,什么时候读到了文件,什么时候网络有了响应再回调给.Net程序,.Net程序再启用线程池的线程继续完成回调后的任务,这也是异步后线程id会改变的原因。

2. 多线程编程(Multithreading Programming)

多线程编程是通过在多个线程上并行执行任务,适用于CPU 密集型任务,如复杂计算、数据处理等。这类操作需要充分利用 CPU 的多核心能力来同时处理多个任务。

在 C# 中,多线程编程可以通过 ThreadThreadPoolTask 等类实现。与异步不同,多线程会创建多个线程来执行不同的任务,这样多个任务可以并发运行。

多线程代码示例

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

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        Console.WriteLine("Starting CPU-intensive tasks...");

        // 启动两个并行任务
        Task task1 = Task.Run(() => PerformCpuIntensiveTask("Task 1"));
        Task task2 = Task.Run(() => PerformCpuIntensiveTask("Task 2"));

        // 等待任务完成
        Task.WaitAll(task1, task2);

        Console.WriteLine("All tasks completed.");
    }

    static void PerformCpuIntensiveTask(string taskName)
    {
        Console.WriteLine($"{taskName} started.");
        for (int i = 0; i < 1000000000; i++)
        {
            // 模拟计算任务
            double x = Math.Sqrt(i);
        }
        Console.WriteLine($"{taskName} completed.");
    }
}

在这个例子中,Task.Run 会在 ThreadPool 中创建并启动新的线程来执行 PerformCpuIntensiveTask,这样 Task 1Task 2 就可以并行执行,提高了 CPU 使用效率。
其实无论是时阻塞的耗时还是复杂计算的耗时,这两个都是耗时,但是这两个又有很大区别,阻塞的耗时可以通过回调,释放当前线程来解决阻塞的问题,但是复杂计算的耗时核回调就没有关系了。举个具体点的例子,要计算一个天文级别的数字,一个人要10天,但是你发现这些数子是可以拆开来分给不同的人计算,最后把结果加起来就行了。这种情况下使用多线程处理计算任务,然后把结果加起来,减少了耗时,同时也提高了cpu的使用率。

总结

  • 异步主要用于非阻塞 I/O 操作,让程序在等待 I/O 时释放资源,适合 I/O 密集型任务。适用于串行任务,不提升单次耗时,但是对整个程序来说可以提示吞吐量。
  • 多线程用于让多个任务并行执行,充分利用 CPU 核心资源,适合 CPU 密集型任务。之前的单次任务可以拆分给不同任务执行的话可以提升耗时,通过消耗硬件资源实现并行或者并发提升效率。

标签:异步,Task,C#,任务,线程,多线程,CPU
From: https://www.cnblogs.com/dx5800/p/18527491

相关文章

  • 07LangChain实战课 - LLM模块使用与自定义模型调用
    LangChain实战课-LLM模块使用与自定义模型调用1.课程简介本节课聚焦于LangChain中的LLM(LargeLanguageModel)模块,探讨如何使用不同的大语言模型,包括开源模型和自定义模型。2.大语言模型的发展Transformer架构:Google在2018年提出的架构,是现代预训练模型的核心。基础......
  • 鸿蒙 Next 安全控件与系统 Picker 深度剖析
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)在开发多语言电商平台方面的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。在鸿蒙Next......
  • Nacos原理汇总
    今天就应某位小伙伴的要求,来讲一讲Nacos作为服务注册中心底层的实现原理不知你是否跟我一样,在使用Nacos时有以下几点疑问:临时实例和永久实例是什么?有什么区别?服务实例是如何注册到服务端的?服务实例和服务端之间是如何保活的?服务订阅是如何实现的?集群间数据是如何同步的?CP还......
  • 08LangChain实战课 - 输出解析器深入与Pydantic解析器实战
    LangChain实战课-输出解析器深入与Pydantic解析器实战1.课程回顾第5课中,我们学习了如何为花和价格生成吸引人的描述,并将这些描述和原因存储到CSV文件中。程序调用了OpenAI模型,并利用了结构化输出解析器以及数据处理和存储工具。2.LangChain中的输出解析器输出解析器......
  • Chromium127编译指南 Mac篇(一)- 环境准备详解
    概述在开源浏览器生态系统中,Chromium始终扮演着举足轻重的角色。作为GoogleChrome的技术基石,它不仅支撑着全球最受欢迎的浏览器之一,更为众多定制化浏览器项目提供了坚实的基础。对于渴望探索浏览器技术深度,或计划开发自有浏览器的工程师而言,深入理解Chromium的编译流程是一项......
  • 基于条件风险价值CVaR的微网动态定价与调度策略(Matlab代码实现)
    ......
  • 质子交换膜燃料电池(PEMFC Simulink模型)
        ......
  • 基于条件风险价值CVaR的微网动态定价与调度策略(Matlab代码实现)
    ......
  • PbootCMS 模板修改 tags 实现 keywords 内容关联匹配
    修改ParserController.php文件:打开 apps/home/controller/ParserController.php 文件,找到以下代码://tags数据参数筛选$where2=array();if($tags){$tags_arr=explode(',',$tags);foreach($tags_arras$value){if($value){if($fuzzy)......
  • pbootcms网站后台增加点击数自定义修改
    打开 /apps/admin/view/default/content/content.html 文件,在 {if([$mod])} 下方添加:<divclass="layui-form-item"><labelclass="layui-form-label">浏览量<spanclass="layui-text-red">*</span></label><......