在Task中调用异步方法

时间:2015-05-07 04:15:11

标签: c# asynchronous

假设我有一个异步方法,例如:

public async Task<int> HeavyWork()
{
    return Task.Run( () => { //some heavy work } );
}

假设我将此任务添加到队列中,将其放入另一个任务中:

...
QueueTask(new Task( () => { HeavyWork(); } ));
...

假设QueueTask方法只是接受一个任务并启动它并等到它完成然后它继续进行下一个任务...启动其中有“HeavyWork()”的任务......它会立即返回吗?既然它是异步的?

1 个答案:

答案 0 :(得分:0)

asyncawait关键字协同工作,允许方法在完成之前返回,然后在以后继续执行。

无法准确解释您的方案中发生的情况,因为您的问题中显示的实际代码很少。从字面上看,您的HeavyWork()方法根本不需要async,因为其中没有使用await

换句话说,async只允许await;它根本不会影响方法的行为。如果你从不在方法中使用await,那么该方法将同步运行,直到它完成任何工作后才返回。

在这种情况下,您将Task对象添加到队列中,队列启动任务,任务调用匿名方法,该方法又调用HeavyWork(),任务不会完成,直到HeavyWork()方法返回,允许匿名方法返回。

这不是很有趣,所以让我们假设在HeavyWork()的某处,你实际上使用await。在这种情况下,HeavyWork()方法将在它完成执行之前返回,在await发生的时刻(即在等待的任何东西返回其等待对象之后 - 通常这是{{1}对象 - 在Task之后的任何事物之前。

就您排队的await而言, 是对Task的调用的完成。因此排队的任务将在HeavyWork()方法实际完成执行之前完成。请注意,这不一定是正确的;在HeavyWork()返回之前执行第一个await之前的任何代码。

请注意,在第二种情况下,如果您想知道HeavyWork()方法何时完成,则需要以某种方式观察返回的HeavyWork()。通常,这将通过Taskawait(对于Task.WhenAll()个对象的集合)或类似机制来完成。

一种可能的方法,因为您的任务队列(正如您所说)同步等待每项任务完成(不一定是最好的设计,但让我们暂时假设它是一个很好的理由在这里),您可以在尝试启动它之前检查每个任务,并且只有在尚未启动时才启动它(尝试启动已启动的任务将导致抛出异常)。

在这种情况下,您只需将Task方法本身的返回值传递给队列:

HeavyWork()

然后,QueueTask(HeavyWork()); 会执行第一个HeavyWork()(可能是相对较快的事情,因为制作方法await的全部理由是让您长时间运行工作异步发生),然后返回一个代表整个方法工作的async对象。

队列在出列特定Task对象时,请注意它已经启动并等待它完成。当Task方法最终完成所有的工作并且结果可用时,队列将看到其等待完成并将继续,就像它已经传递{{1}一样包装一些同步方法。


请注意,上述所有内容都必然含糊不清。鉴于原始问题的模糊性,提供具体建议是不可能的。但我希望这有助于澄清HeavyWork()Task如何协同工作,特别是它们如何在您描述的模糊陈述的情景中发挥作用。