我正在阅读http://msdn.microsoft.com/en-US/library/vstudio/hh191443.aspx。 示例代码:
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
该页面还说:
async和await关键字不会导致创建其他线程。异步方法不需要多线程,因为异步方法不能在自己的线程上运行
这是否“没有创建其他线程”是否适用于标记为async?
的方法的范围我想,为了让GetStringAsync和AccessTheWebAsync同时运行(否则GetStringAsync将永远不会像AccessTheWebAsync现在拥有的那样完成),最终GetStringAsync必须在AccessTheWebAsync线程的不同线程上运行。
对我来说,编写异步方法只有在没有添加更多线程时才有用,因为它等待的方法也是异步的(已经使用额外的线程来并行执行它自己的事情)
我的理解是否正确?
答案 0 :(得分:13)
这是async
力量的关键。 GetStringAsync
和其他自然异步操作不需要线程。 GetStringAsync
只发送HTTP请求并注册回调以在服务器回复时运行。只需等待服务器响应就不需要线程。
实际上,线程池只使用了一小部分。在上面的示例中,GetStringAsync
注册的回调将在线程池线程上执行,但它只是通知AccessTheWebAsync
它可以继续执行。
我有async
intro blog post你可能会觉得有帮助。
答案 1 :(得分:2)
我想,为了让GetStringAsync和AccessTheWebAsync 同时运行 ......
它们不会同时运行(至少不是你想的那样)。现在,如果HttpClient.GetStringAsync本身
关键是将方法声明为async
和/或使用await
,不会导致您创作的方法在单独的线程上运行(您必须这样做)明确地说。)
注意:
如果没有其他异步方法的代码(或文档),您实际上并不知道它有多少是同步运行的。在该方法执行await
或显式启动另一个线程(通常是通过启动新的Task
)
答案 2 :(得分:0)
如果有必要,可以从线程池中获取一个线程来进行操作。在控制台(不讨论UI线程或IO线程)的情况下,当前线程进入控制台并且执行另一个线程,并且该新线程是执行剩余操作的线程。
答案 3 :(得分:-3)
作者在这里说的是,在某处简单地使用async和await关键字不会导致当前方法在不同的线程上运行。我们来调查一下提供的代码会发生什么。
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
到目前为止,所有事情都在一个线程中执行。此时,client.GetStringAsync调用可以剥离一个新线程(虽然这不是任何异步方法的保证)。应该注意的是,GetStringAsync方法基本上是在当前线程上启动的(例如实际进行调用),但是一旦返回,读取响应将在不同的线程中执行。这由它返回一个Task对象来表示。任务可以表示已经完成的工作,当前正在执行的辅助线程,或者只是安排稍后执行的工作单元。
DoIndependentWork();
现在,在呼叫排队(或可能已发送)后,我们的主线程上会执行此操作。因此,这可能在等待返回请求时发生。请注意,我们仍然是我们的主要线程。
string urlContents = await getStringTask;
此时,我们的线程返回。 .NET将创建一个包含方法其余部分的延续函数(return urlContents.Length;),一旦getStringTask在它自己的线程上完成,它将自动为我们调用。此时,新线程将获取延续。
通过所有这些,我们在async方法中编写的全部内容,直到await关键字,都在一个线程中运行。当然,我们调用了另一种可能会产生另一个线程的方法,但是我们没有采取任何措施来仅使用async / await关键字来创建另一个线程。最后的延续可能由不同的线程调用,但是在我们的初始函数实际返回之后(这就是为什么我们的函数返回一个Task对象,表示当对该函数的任何调用返回时可能尚未完成的工作)