c#中的异步操作和线程

本文关键字:线程 异步操作 | 更新日期: 2023-09-27 17:52:44

异步编程是一种在后台调用长时间运行的方法以使UI线程保持响应的技术。它应该在调用web服务或数据库查询或任何I/O绑定操作时使用。当异步方法完成时,它将结果返回给主线程。通过这种方式,程序的主线程不必等待I/O绑定操作的结果,并在不阻塞/冻结UI的情况下继续执行。

据我所知,异步方法在后台工作线程上执行。运行时可以从线程池中获取线程,也可以为其创建一个全新的线程来执行。

但是我在许多帖子中读到,异步操作可能在单独的线程上执行,或者不使用任何线程。现在我很困惑。

1)你能帮助澄清在什么情况下异步操作将不使用线程吗?

2)处理器内核在异步操作中的作用是什么?

3)它与多线程有何不同?我只知道一件事,多线程对于计算约束的操作很有用。

请帮。

c#中的异步操作和线程

IO(假设是网络上的数据库操作)是一个很好的例子:

  1. 你基本上只是注册一个回调,当io操作完成时,操作系统将最终调用(可能在一个新创建的线程上)。没有线程坐在那里等待——复活将由硬件事件触发(或者至少由通常在用户空间之外的操作系统进程触发)

  2. 它可能没有(见1)

  3. 在多线程中,你使用多个线程(你的后台线程),有一个可能闲置坐在那里什么也不做(但使用系统资源)-这当然是不同的,如果你一些计算(所以线程不是空闲等待外部结果)-在那里使用后台工作线程

  4. 是有意义的

异步操作实际上并不意味着它们是如何被处理的,只是它们希望选择稍后将结果返回给您。举例:

  • 它们可能(正如你所提到的)将一个计算绑定的任务分离到一个独立的线程上,但这不是唯一的用例。
  • 它们有时可能在启动它们的调用中同步完成,在这种情况下不需要使用额外的线程。如果已经有足够的缓冲区内容(输入)或空闲缓冲区空间(输出)来处理请求,则可能发生这种情况。
  • 它们可能只是把长时间运行的I/O请求丢给系统;在这种情况下,回调可能发生在后台线程接收到I/O完成端口的通知后。
  • 在完成时,回调可以稍后在同一线程上传递;这对于UI框架内的事件尤其常见,例如WebBrowser中的导航。

异步性不涉及线程。它是关于在"状态机"内部处理的某种回调(不完全正确,但你可以把它想象成事件)。异步不会引发线程,也不会大量分配系统资源。您可以运行任意数量的异步方法。

线程在你的系统上有一个真正的暗示,你有一个庞大但有限的数量,你可以一次拥有。

Io操作大多与其他控制器(HDD, NIC,…)相关。如果你创建了一个线程,那么你的应用程序的一个线程就会无事可做,等待控制器完成。在异步中,正如Carsten和Jeffrey已经提到的,你只是得到某种回调机制,所以你的线程继续做其他工作,方法等等。

还要记住,每个线程消耗资源(RAM,性能,处理垃圾收集变得更糟,…),甚至可能在异常(OutOfMemoryException…)

那么何时使用线程呢?当然,只有当你真的需要的时候。如果有异步api,请使用它,除非你有非常重要的理由不使用它。在过去的日子里,异步api真的很痛苦,这就是为什么许多人在需要异步时使用线程的原因。

例如node.js完全拒绝使用多线程!

如果你处理多个请求,这是特别重要的,例如在服务/网站中,总是有工作要做。Jeffrey Richter也做了一个简短的网络广播,帮助我理解

也可以看看这篇MSDN文章PS:作为一个副作用,使用async和await的源代码往往更具可读性