【发布时间】:2019-03-11 21:03:32
【问题描述】:
我设法在互联网上找到了一些类似问题的答案,但没有人解释得足以让我理解下面代码的不同之处。
我知道 await 与 .Result 不同,它不会阻塞调用线程。但是,如果我们试图从一个任务中访问这个属性,并且无论如何都不会阻止它呢?
比如这个有什么区别
public static Task PrintPageAsync(string url)
{
return Task.Run(() =>
{
WebRequest webRequest = WebRequest.Create(url);
WebResponse response = webRequest.GetResponseAsync().Result;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string text = reader.ReadToEndAsync().Result;
Console.WriteLine(text);
}
});
}
还有这个
public static async Task PrintPageAsync(string url)
{
WebRequest webRequest = WebRequest.Create(url);
WebResponse response = await webRequest.GetResponseAsync();
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string text = await reader.ReadToEndAsync();
Console.WriteLine(text);
}
}
【问题讨论】:
-
没关系,区别还是会阻塞。像这样将异步与阻塞混合在一起可能会导致代码锁定。
-
这很有趣,“它会阻塞”是什么意思?我在 Main 方法中使用它,如下所示: PrintPageAsync(@"en.wikipedia.org/wiki/Instruction-level_parallelism"); while (true) { Console.Write("*"); } 无论我使用哪一个,它都不会阻塞。它开始立即打印星星,一段时间后它会打印页面并在此之后仍在打印星星。
-
那是因为第一个是在另一个线程中启动的。在这种情况下,您不妨调用同步的
ReadToEnd。删除Task.Run看看会发生什么。 -
我想我明白了,但我的意思是当我使用Task.Run时两者有什么区别,所以它从另一个线程开始。调用它时它的行为是否会与异步方法不同?
-
最终区别在于使用了多少线程。对于这个简单的示例来说,差别不大,但如果这是在 Web 服务调用后面的服务器上的代码,那么当您收到许多请求并且服务器由于一堆阻塞线程而变慢时,您就会遇到扩展问题。
标签: c# multithreading asynchronous async-await task