什么是异步方法?

17

什么是异步方法?我认为我知道,但我总是把它与并行混淆。我不确定异步方法和并行之间的区别。

另外,使用线程类和异步类有何区别?

编辑

演示异步、线程和并行之间差异的一些代码将会很有用。


你是在询问在单独线程中执行I/O和使用I/O完成端口的异步模式之间的区别吗? - mbeckish
请看这里- 对于异步操作:http://msdn.microsoft.com/en-us/magazine/cc164036.aspx。对于多线程:http://arstechnica.com/features/2002/10/hyperthreading/。 - Sunil
4个回答

26

什么是异步方法?

当我们讨论潜在的耗时操作时,就会涉及到异步方法。通常情况下,我们需要这样的操作完成才能有意义地继续程序执行,但我们不想“暂停”直到操作完成(因为暂停可能会导致 UI 停止响应,这显然是不可取的)。

异步方法是一种我们调用以开始耗时操作的方法。该方法应该做必要的事情以启动操作,并"非常快"地返回结果,以避免任何处理延迟。

异步方法通常返回一个标记,调用者可以使用该标记查询操作是否已经完成以及其结果是什么。在某些情况下,它们接受回调(委托)作为参数;当操作完成时,回调被调用以向调用者发出信号,表明他们的结果准备就绪并将其传递回来。 这个 是一个常用的回调签名,当然在一般情况下回调可以看起来像任何形式。

那么,实际上谁运行了耗时的操作?

我之前说过,异步方法启动了一个耗时的操作,但在这个上下文中,“启动”是什么意思呢?由于该方法立即返回结果,实际的工作在哪里执行?

一般情况下,一个执行线程需要监视该过程。由于不是调用异步方法的线程暂停,那么谁会暂停呢?答案是从托管线程池中选择出来的一个线程。

与线程有什么关系?

在这种情况下,“线程”指的是你显式地开启自己的线程并将其委托以同步方式执行相应的任务。该线程将会阻塞一段时间,并且可能会在操作完成时向您的“主”线程发出信号(这时主线程可以继续执行)。

这个指定的工作线程可能会被从线程池中取出(注意:在线程池线程中进行非常长时间的处理不推荐!)或者它可能是你为此目的启动的线程之一。


异步处理的一个很大的优势是它实际上不会阻塞任何线程。 - svick
@svick:这最终取决于操作和操作系统提供的相关设施。然而,阻塞部分并不是讨论的重点,所以我将其编辑掉了,还有其他一些东西。感谢您的参与。 - Jon

21
首先,什么是方法和线程? 方法是一个“工作单元”,可以执行有用的副作用(例如写入文件)或计算结果(例如制作分形位图)。 线程是执行该工作的“工作者”。
如果要使用同步方法 - 获取副作用或结果 - 则您的线程必须从请求工作开始时一直保持空闲状态,直到完成为止。
异步方法是指您的线程告诉方法它需要完成工作,并且方法说:“好的,我会做到,并在完成时通知您”。 通常,异步方法通过创建另一个工作者 - 从池中获取线程来完成。 特别是在方法需要重度使用 CPU 的情况下。 但并不总是这样; 异步方法不一定要启动另一个线程。
这样讲清楚了吗?

那么一个线程告诉方法“做这个”,然后等待响应,另一个线程实际上执行这个响应;而第一个线程在等待响应时可以做一些有用的工作,对吗? - CrazyMan
1
@CrazyMan:这可以是一种工作方式,但异步编程并不要求两个工作者。想象一下你把面包放在烤面包机里等待它烤好后,你就可以煮鸡蛋了。虽然厨房里只有一个“线程”——一个人在做饭,但你却能在等面包的时候完成煮鸡蛋的工作。 - Eric Lippert

10

假设你需要打扫房子,做晚饭并哄孩子睡觉。

同步:

你先打扫房子,然后做晚饭,最后哄孩子睡觉。

并行:

你雇了3个人来分别打扫房子,做晚饭和哄孩子睡觉。但是你不相信他们,所以保持监督角色,观察他们并等待他们完成工作。只有当他们全部完成时,他们才会得到报酬。

异步:

你让一个孩子打扫房子,另一个孩子做晚饭。每个孩子完成自己的家务后,他们自己去睡觉,而你则坐在电视机前,轻松地品尝着一杯葡萄酒。


14
最后一段很有趣,但可以更准确。我认为“asynchronous”可以解释为“你把水烧开,在水开始沸腾之前你有些时间捡起地上的外套。然后把面条放进去,接着你就有时间开始洗衣服。等到洗衣机运转时,你可以吃晚饭。然后你可以哄孩子睡觉,最后再完成清洁工作。异步编程的关键在于将工作分成小块,这样你可以在等待高延迟操作期间做其他事情。 - Eric Lippert
是的,但主要的重点是并行,主线程在继续之前等待子线程完成。异步的,子线程在主线程做自己的事情时工作。(用最简单的术语来说!) :) - anothershrubery
5
@anothershrubery 不,这不是真的。首先,在并行环境中,您可以使主线程执行工作。您甚至可以在并行环境中让主线程不观察其他线程。并行化意味着有多个东西在进行工作,没有多也没有少。异步性意味着启动工作、做其他事情,然后根据早期启动的工作结果可能会做一些事情。这可能涉及并行化,但也可能不涉及,就像Eric所描述的那样。您可以异步地完成家务,但不能并行化。 - Servy
9
@Servy: 或者,另一个经典的例子是:你可以在怀孕期间继续工作,但九个女人不能在一个月内生出一个婴儿。这个操作是异步的--你可以在等待结果的时候做其它事情--但它不是可并行化的--任务的部分不能轻易地分配给独立的工作者。 - Eric Lippert

1
首先你需要明白的是,如果想要并行处理,所有结构都需要并行。也就是说,如果你有一个异步方法,你需要使用异步调用。 在Web服务或Web内容中,异步方法可以(只是其中一种方式)使用异步的AJAX进行调用。在一个方法中,你可以拥有多个线程,这是异步方法和多线程之间的关键区别。 而主要的区别是:标准方法和异步方法之间的区别在于,如果你同时使用异步调用(如AJAX)对同一个控制器的标准方法进行两次调用,第二次调用将在第一次调用完成后才开始进行;但如果你调用的方法是异步的,那么这两次调用将同时开始。在多核服务器上,它可以达到标准速度的两倍(2次调用)。 并行处理的速度通过law来衡量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接