C#中async/await之线程上下文工作原理

yizhihongxing

首先让我们来了解一下async/await在C#中的基本概念和原理。

什么是async/await?

async/await是C#中异步编程的关键字,是一种改进了的异步编程模型。它基于任务(Task)和协程(Coroutine),通过简明的语法糖,使得异步编程变得更加易于理解和使用。

它的核心思想是将异步操作打包成一个任务(Task),在需要时使用await关键字暂停当前线程,等待该任务执行完成后再继续执行下面的代码。

异步/同步上下文

在C#中,异步代码和同步代码运行在不同的上下文中,异步操作将在一些特定的上下文中运行,比如UI线程、ASP.NET线程等,这些上下文被称为SynchronizationContext。同步代码的上下文是线程池或者 ThreadPool。

异步/同步上下文的切换机制大大影响了程序的性能和质量。如果上下文切换的代价太高,异步编程的优势就无法体现。

await的工作原理

当程序遇到一个await关键字的时候,它会将当前状态保存下来,并将控制流递交给SynchronizationContext,当异步任务完成后,SynchronizationContext会通知程序,将保存的状态恢复并执行下面的代码。

此处也需要注意:在异步任务完成后,它应该是运行在另一个上下文中,即异步上下文,为了确保这个异步任务在异步上下文中运行,开发者需要在异步操作函数最开始加上ConfigureAwait(false)。

示例说明

下面演示一下async/await在C#中的应用,这里我们使用一个简单的例子,获取指定url的html内容。

public async Task<string> GetHtmlAsync(string url)
{
    using (var httpClient = new HttpClient())
    {
        var html = await httpClient.GetStringAsync(url).ConfigureAwait(false);
        return html;
    }
}

在这个代码片段中,我们生成一个HttpClient实例,调用GetStringAsync方法获取目标url的html内容,并在字符串后面加上ConfigureAwait(false)。在这里ConfigureAwait(false)的作用是告诉程序,这个异步操作不需要回到原本的上下文中去。

下面我们在Console程序里面调用该方法,观察异步线程上下文的切换。

static async Task Main(string[] args)
{
    Console.WriteLine($"Main Start,ThreadId: {Thread.CurrentThread.ManagedThreadId}");

    var html = await GetHtmlAsync("https://www.baidu.com");
    Console.WriteLine($"Html length: {html.Length},ThreadId: {Thread.CurrentThread.ManagedThreadId}");

    Console.WriteLine("Main End");
}

在这个代码片段中,我们使用await关键字调用GetHtmlAsync异步方法,观察在await后面的代码在哪个线程上执行。我们可以看到,在GetHtmlAsync方法中的await后面的代码运行在了不同的线程上。

通过上述示例,我们可以了解到async/await在C#中的工作机制和应用场景,更多线程相关知识可以参考C#官方文档,深入了解异步编程。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#中async/await之线程上下文工作原理 - Python技术站

(0)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • C#实现基于加减按钮形式控制系统音量及静音的方法

    下面我来详细讲解如何使用C#实现基于加减按钮形式控制系统音量及静音的方法。 准备工作 在开始编写代码之前,需要确保以下几点: 了解C#语言基础知识; 熟悉Windows API编程; 确认开发环境已经安装了以下库:System.Runtime.InteropServices和CoreAudioApi。 实现步骤 第一步:获取系统音量 使用CoreAudioA…

    C# 2023年6月7日
    00
  • 教你创建一个带诊断工具的.NET镜像

    教你创建一个带诊断工具的.NET镜像 在.NET应用程序中,诊断工具是一项非常重要的任务,它可以帮助您跟踪应用程序的运行情况并诊断问题。在本攻略,我们将详细讲解如何创建一个带诊断工具的.NET镜像,并提供两个示例说明。 步骤一:创建Dockerfile 要创建一个带诊断工具的.NET镜像,您需要创建一个Dockerfile。以下是Dockerfile的示例代…

    C# 2023年5月17日
    00
  • ASP.NET Ref和Out关键字区别分析

    ASP.NET中的Ref和Out关键字都是用来传递参数的,但它们之间的区别是很明显的。 Ref关键字 Ref关键字用于向方法中传递参数。使用该关键字传递参数意味着你正在传递参数的引用(内存地址),而不是参数本身。因此,任何对参数的更改也会对变量本身产生影响。 Ref示例: public void Modify(ref int num) { num += 10…

    C# 2023年5月31日
    00
  • .NET发送邮件遇到问题及解决方法

    . 简介 在进行.NET开发时,我们会经常用到邮件发送功能。然而,在使用.NET发送邮件时,可能会遇到一些问题,例如邮件发送失败、被当作垃圾邮件等。本攻略将为大家介绍.NET发送邮件遇到的问题及解决方法。 . 常见问题及解决方法 1. 发送邮件失败 如果发送邮件失败,可以根据以下步骤来排查问题: (1) 确认SMTP服务器地址和端口号是否正确 using S…

    C# 2023年5月31日
    00
  • 深入解析C#中的abstract抽象类

    深入解析C#中的abstract抽象类 介绍 在C#中,抽象类是一种不能直接实例化的类,它通常用于定义一个接口,强制子类实现一些方法。抽象类中至少有一个抽象方法,这些方法没有实现,只有定义。在子类中,这些抽象方法必须被实现才能使用。抽象类是OOP中的核心概念之一,深入理解抽象类对于程序员来说至关重要。 创建抽象类 在C#中,通过使用abstract关键字来定…

    C# 2023年6月1日
    00
  • C#实现DataTable映射成Model的方法(附源码)

    C#实现DataTable映射成Model的方法 简介 在开发中,我们有时候会从数据库中获取DataTable对象,但是DataTable中的数据并不能直接用于操作,需要将DataTable映射成相应的Model对象,这里提供一种比较好用的方法。 实现过程 步骤如下: 定义Model类,具体模型字段需要与DataTable中的列名对应。 csharppubl…

    C# 2023年5月31日
    00
  • c# 编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)

    使用 Markdown 格式,我将为您详细介绍如何编写一个异步写日志的实用工具类(LogAsyncWriter)。 LogAsyncWriter 类的设计 LogAsyncWriter 是一个轻量级的异步写日志工具类。它的设计主要包括以下内容: 属性 LogFilePath: 可读写的字符串属性,表示日志文件的完整路径。默认为项目根目录下的 log.txt …

    C# 2023年6月1日
    00
  • C#中static void Main(string[] args) 参数示例详解

    让我来详细讲解一下 “C#中static void Main(string[] args) 参数示例详解” 的完整攻略。 什么是Main方法 在学习C#编程的时候,我们一般都会接触到一个Main方法。这个Main方法是C#程序的入口方法,也是程序运行的起点。 了解Main方法的参数 在C#的Main方法中,会有一个参数,这个参数是个字符串数组类型的参数,它的…

    C# 2023年6月7日
    00
合作推广
合作推广
分享本页
返回顶部