C# 异步调用同步方法比自然异步方法更快地完成任务

C# 异步调用同步方法比自然异步方法更快地完成任务,c#,async-await,task-parallel-library,C#,Async Await,Task Parallel Library,对不起,标题不好。我目前正在学习第三方物流和阅读博客文章的国家 异步调用同步方法的能力对可伸缩性没有任何影响,因为通常情况下,您仍然在消耗与同步调用同步方法相同的资源量。事实上,您使用的资源更多,因为调度某些内容会产生开销 所以我想让我们试试,我创建了一个演示应用程序,它使用WebClient的DownloadStringTaskAsync和DownloadStringSynchronous方法 我的演示应用程序有两种方法 下载HtmlNotAsyncInAsyncWay 这为同步方法Downl

对不起,标题不好。我目前正在学习第三方物流和阅读博客文章的国家

异步调用同步方法的能力对可伸缩性没有任何影响,因为通常情况下,您仍然在消耗与同步调用同步方法相同的资源量。事实上,您使用的资源更多,因为调度某些内容会产生开销

所以我想让我们试试,我创建了一个演示应用程序,它使用WebClient的DownloadStringTaskAsync和DownloadStringSynchronous方法

我的演示应用程序有两种方法

下载HtmlNotAsyncInAsyncWay

这为同步方法DownloadString提供了异步方法包装器,而同步方法DownloadString的伸缩性不好

下载HTMLCSASync

这将调用异步方法DownloadStringTaskAsync

我从这两种方法中创建了100个任务,并比较了所消耗的时间,发现选项1所消耗的时间比第二个要少。为什么?

这是我的密码

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);
        }
    }
是dotnetfiddle链接


为什么第一个选项比第二个选项完成的时间要短?

您实际上并没有测量任何东西

Task.whenall任务;返回完成所有这些任务的任务。 你对那项任务什么都不做,所以你不会等待任何事情完成

因此,您只需测量每个备选方案的同步初始化。仅将一个委托排队到线程池;与设置HTTP请求相比,它所做的工作更少

事实上,您正在使用更多的资源,因为调度某些内容会产生开销

即使像SLaks建议的那样,您正确地等待任务,也几乎不可能准确地测量此开销

您的测试正在下载需要网络访问的网页。
您试图测量的开销比网络延迟的变化要小得多,它会在噪音中丢失。

我补充说,试试Task.WaitAll而不是噢,天哪。这么愚蠢的问题。似乎我需要像Task.WhenAlltasks.wait一样调用wait;要测量消耗的时间…@JenishRabadiya或,只需按照Yorye的建议使用Task.WaitAll