Sorry for bad title. I am currently learning TPL and reading this blog article which states
抱歉标题不好。我目前正在学习TPL并阅读这篇博客文章
The ability to invoke a synchronous method asynchronously does nothing for scalability, because you’re typically still consuming the same amount of resources you would have if you’d invoked it synchronously (in fact, you’re using a bit more, since there’s overhead incurred to scheduling something ).
异步调用同步方法的能力对可伸缩性没有任何作用,因为如果你同步调用它,你通常仍会消耗相同数量的资源(事实上,你使用的更多,因为它有开销因安排某事而招致)。
So I thought let's give it a try and I created demo application that uses WebClient
's DownloadStringTaskAsync
and DownloadString
(synchronous) method.
所以我想让我们试一试,我创建了使用WebClient的DownloadStringTaskAsync和DownloadString(同步)方法的演示应用程序。
My demo application is having two methods
我的演示应用程序有两种方法
-
DownloadHtmlNotAsyncInAsyncWay
This provides asynchronous method wrapper around the synchronous method
DownloadString
which should not scale good.这提供了同步方法DownloadString的异步方法包装器,它不应该扩展良好。
-
DownloadHTMLCSAsync
This calls async method DownloadStringTaskAsync.
这会调用异步方法DownloadStringTaskAsync。
I created 100 task from both methods and compared time consumed and found that option 1 consumed less time compare to second. why?
我从两种方法中创建了100个任务并比较了消耗的时间,发现选项1比第二个消耗的时间少。为什么?
Here is my code.
这是我的代码。
using System;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
const int repeattime = 100;
var s = new Sample();
var sw = new Stopwatch();
var tasks = new Task<string>[repeattime];
sw.Start();
for (var i = 0; i < repeattime; i++)
{
tasks[i] = s.DownloadHtmlNotAsyncInAsyncWay();
}
Task.WhenAll(tasks);
Console.WriteLine("==========Time elapsed(non natural async): " + sw.Elapsed + "==========");
sw.Reset();
sw.Start();
for (var i = 0; i < repeattime; i++)
{
tasks[i] = s.DownloadHTMLCSAsync();
}
Task.WhenAll(tasks);
Console.WriteLine("==========Time elapsed(natural async) : " + sw.Elapsed + "==========");
sw.Reset();
}
}
public class Sample
{
private const string Url = "https://www.google.co.in";
public async Task<string> DownloadHtmlNotAsyncInAsyncWay()
{
return await Task.Run(() => DownloadHTML());
}
public async Task<string> DownloadHTMLCSAsync()
{
using (var w = new WebClient())
{
var content = await w.DownloadStringTaskAsync(new Uri(Url));
return GetWebTitle(content);
}
}
private string DownloadHTML()
{
using (var w = new WebClient())
{
var content = w.DownloadString(new Uri(Url));
return GetWebTitle(content);
}
}
private static string GetWebTitle(string content)
{
int titleStart = content.IndexOf("<title>", StringComparison.InvariantCultureIgnoreCase);
if (titleStart < 0)
{
return null;
}
int titleBodyStart = titleStart + "<title>".Length;
int titleBodyEnd = content.IndexOf("</title>", titleBodyStart, StringComparison.InvariantCultureIgnoreCase);
return content.Substring(titleBodyStart, titleBodyEnd - titleBodyStart);
}
}
Here is dotnetfiddle link.
这是dotnetfiddle链接。
Why did first option completed in less time than second time?
为什么第一个选项在比第二次更短的时间内完成?
2 个解决方案
#1
You aren't actually measuring anything.
你实际上并没有测量任何东西。
Task.WhenAll(tasks);
returns a Task
of the completion of all of those tasks.
You don't do anything with that task, so you aren't waiting for anything to finish.
Task.WhenAll(任务);返回完成所有这些任务的任务。你没有对这项任务做任何事情,所以你不等待任何事情完成。
Therefore, you're just measuring the synchronous initialization of each alternative. Task.Run()
just queues a delegate to the thread pool; it does less work than setting up an HTTP request.
因此,您只需测量每个备选方案的同步初始化。 Task.Run()只是将一个委托排队到线程池;它比设置HTTP请求的工作少。
#2
in fact, you’re using a bit more, since there’s overhead incurred to scheduling something
事实上,你使用的更多,因为调度某些东西会产生开销
Even if you were correctly awaiting the tasks, as SLaks suggested, it would be near impossible to accurately measure this overhead.
正如SLaks所说,即使你正确地等待任务,也几乎不可能准确地测量这种开销。
Your test is downloading a webpage, which requires network access. The overhead you're trying to measure is soooo much smaller than the variance in the network latency, that it would be lost in the noise.
您的测试是下载需要网络访问的网页。您尝试测量的开销远小于网络延迟的变化,它会在噪声中丢失。
#1
You aren't actually measuring anything.
你实际上并没有测量任何东西。
Task.WhenAll(tasks);
returns a Task
of the completion of all of those tasks.
You don't do anything with that task, so you aren't waiting for anything to finish.
Task.WhenAll(任务);返回完成所有这些任务的任务。你没有对这项任务做任何事情,所以你不等待任何事情完成。
Therefore, you're just measuring the synchronous initialization of each alternative. Task.Run()
just queues a delegate to the thread pool; it does less work than setting up an HTTP request.
因此,您只需测量每个备选方案的同步初始化。 Task.Run()只是将一个委托排队到线程池;它比设置HTTP请求的工作少。
#2
in fact, you’re using a bit more, since there’s overhead incurred to scheduling something
事实上,你使用的更多,因为调度某些东西会产生开销
Even if you were correctly awaiting the tasks, as SLaks suggested, it would be near impossible to accurately measure this overhead.
正如SLaks所说,即使你正确地等待任务,也几乎不可能准确地测量这种开销。
Your test is downloading a webpage, which requires network access. The overhead you're trying to measure is soooo much smaller than the variance in the network latency, that it would be lost in the noise.
您的测试是下载需要网络访问的网页。您尝试测量的开销远小于网络延迟的变化,它会在噪声中丢失。