操作系统必须支持异步方法,或者是异步程序级功能

时间:2016-12-01 17:21:27

标签: c# asynchronous

教程有时指向自己的异步方法的实现,例如这段代码:

async public static Task GetHttpResponseAsync()
{
   using (HttpClient httpClient = new HttpClient())
   {
       HttpResponseMessage response = await httpClient.GetAsync(...);
       Console.WriteLine(response.Something);
   }            
}

我清楚的是异步工作通常如何,但没有一个教程解释内部如何实现

httpClient.GetAsync(...);

了解asynchoronus代码如何在细节中工作非常重要。令我好奇的是,如果GetAsync的内部操作(那些方法或其他异步方法)是在执行此代码的某种容器中注册的?操作系统是否必须支持异步方法(例如,它使用的是windows api)?如果我想实现我自己的异步文件下载器(从磁盘而不是.NET框架的必要部分),我将如何实现它,我应该在某处注册我的方法以进一步调用?

我很清楚,在内部,编译器生成状态机,在DoSomething()方法执行它所需的操作之后,它只是再次调用此状态机以在等待之后恢复执行代码。

另外我不清楚的是异步代码如何在同一个线程上运行。我认为维护状态机必须在同一个线程上,但httpClient.GetAsync()的代码如何在同一个线程上运行,并且不会中断其他操作(f.e gui)。必须有一些东西使这个代码在单独的线程上运行(在所有情况下)。我错了吗?我错过了什么?

对我的问题的补充说明:在JavaScript中,据我所知和理解,异步方法的工作原理是将它们注册到某种容器(在不同的线程上逐个运行它们)来执行此方法。在完成方法执行后,结果将返回给用户上下文,对我来说很清楚,这是否在这里工作?

1 个答案:

答案 0 :(得分:2)

简而言之,必须在操作系统级别提供真正的异步。正如您所指出的,async / await是一种语言级功能,它使用编译器生成的状态机来解析"分解"您的方法可以异步运行,但它依赖于操作系统原语(中断,线程)以异步方式实际执行此工作。

但是,重要的是要注意,通常是为处理异步操作而创建的线程。我将按照这篇专业撰写的文章来描述为什么会这样:http://blog.stephencleary.com/2013/11/there-is-no-thread.html

在Windows上,执行异步工作的主要机制是I/O Completion Ports。这是一个Windows API,由许多.NET类型引用,包括您正在使用的HttpClient

请注意,对于非I / O操作,您也可以始终使用Threads,或者更好地使用Thread Pool API来执行将异步完成的后台工作。

Windows API中的ReadFile(或更新ReadFileEx)函数旨在与异步I / O一起使用。当您调用ReadFile时,您可以使用FILE_FLAG_OVERLAPPED标志并将OVERLAPPED结构传递给lpOverlapped参数,从而启用异步读取。我建议您使用此API来设计文件下载程序。

总结:

相关问题