Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “一个”的开销是多少;同步的;异步方法?_C#_Async Await - Fatal编程技术网

C# “一个”的开销是多少;同步的;异步方法?

C# “一个”的开销是多少;同步的;异步方法?,c#,async-await,C#,Async Await,这里是一个方法返回任务的基准,但在后台同步运行 class MainClass { public static async Task<int> UsingAsyncModifier() { return 10; } public static Task<int> UsingTaskCompletionSource() { TaskCompletionSource<int> tcs = n

这里是一个方法返回任务的基准,但在后台同步运行

class MainClass
{
    public static async Task<int> UsingAsyncModifier()
    {
        return 10;
    }

    public static Task<int> UsingTaskCompletionSource()
    {
        TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
        tcs.SetResult(10);
        return tcs.Task;
    }

    public static Task<int> UsingTaskFromResult()
    {
        return Task.FromResult(10);
    }

    public static void Main(string[] args)
    {
        DateTime t = DateTime.Now;
        const int repeat = 10000; // Results volatile while repeat grows.
        Console.WriteLine("Repeat {0} times.", repeat);

        int j = 0;
        for (int i = 0; i < repeat; i++)
        {
            j += UsingAsyncModifier().Result;
        }
        Console.WriteLine("UsingAsyncModifier: {0}", DateTime.Now - t);
        t = DateTime.Now;

        for (int i = 0; i < repeat; i++)
        {
            j += UsingTaskCompletionSource().Result;
        }
        Console.WriteLine("UsingTaskCompletionSource: {0}", DateTime.Now - t);
        t = DateTime.Now;

        for (int i = 0; i < repeat; i++)
        {
            j += UsingTaskFromResult().Result;
        }
        Console.WriteLine("UsingTaskFromResult: {0}", DateTime.Now - t);
    }
}
重复10000次,使用TaskFromResult比使用SyncModifier快10倍

重复100000次,使用TaskFromResult比使用SyncModifier快2倍

重复1000000次,使用SyncModifier比使用TaskFromResult稍微快一点

我认为,
async
修饰符刚刚创建了一个已完成的任务,类似于
Task.FromResult()
这样做。但基准并不能证明我的想法。
为什么?

当我看到使用
DateTime
得到类似的结果时,使用
Stopwatch
进行时间测量表明,使用
UsingAsyncModifier()
进行迭代所需的时长是使用
UsingTaskCompletionSource()
UsingTaskFromResult()
进行迭代所需时长的两倍(两者显示的平均时长)即使有1000次迭代

以下是输出:

Repeat 1000000 times.
UsingAsyncModifier: 5458
UsingTaskCompletionSource: 2838
UsingTaskFromResult: 2556
使用您的代码使用秒表

class Program
{
     public static async Task<int> UsingAsyncModifier()
    {
        return 10;
    }

    public static Task<int> UsingTaskCompletionSource()
    {
        TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
        tcs.SetResult(10);
        return tcs.Task;
    }
    public static Task<int> UsingTaskFromResult()
    {
        return TaskEx.FromResult(10);
    }
    static void Main(string[] args)
    {
      //DateTime t = DateTime.Now;
      Stopwatch timer = new Stopwatch();
      const int repeat = 1000*1000; // Results volatile while repeat grows.
      Console.WriteLine("Repeat {0} times.", repeat);

        int j = 0;
        //DateTime t = DateTime.Now;
        timer.Start();
        for (int i = 0; i < repeat; i++)
        {
            j += UsingAsyncModifier().Result;
        }
        timer.Stop();
        Console.WriteLine("UsingAsyncModifier: {0}"
                          , timer.ElapsedMilliseconds);
        //t = DateTime.Now;
        timer.Reset();

        j = 0;

        timer.Start();
        for (int i = 0; i < repeat; i++)
        {
            j += UsingTaskCompletionSource().Result;
        }
        timer.Stop();
        Console.WriteLine("UsingTaskCompletionSource: {0}"
                           , timer.ElapsedMilliseconds);
        //t = DateTime.Now;
        timer.Reset();
        j = 0;
        timer.Start();
        for (int i = 0; i < repeat; i++)
        {
          j += UsingTaskFromResult().Result;
        }
        timer.Stop();
        Console.WriteLine("UsingTaskFromResult: {0}"
                          , timer.ElapsedMilliseconds);

        Console.ReadLine();
    }
}
类程序
{
使用SyncModifier()的公共静态异步任务
{
返回10;
}
使用TaskCompletionSource()的公共静态任务
{
TaskCompletionSource tcs=新的TaskCompletionSource();
tcs.SetResult(10);
返回tcs.Task;
}
使用TaskFromResult()的公共静态任务
{
返回TaskEx.FromResult(10);
}
静态void Main(字符串[]参数)
{
//DateTime t=DateTime.Now;
秒表计时器=新秒表();
const int repeat=1000*1000;//当repeat增长时,结果不稳定。
WriteLine(“重复{0}次。”,重复);
int j=0;
//DateTime t=DateTime.Now;
timer.Start();
for(int i=0;i
Stephen Toub在他的“”中解释:

使用同步代码时,将禁用具有空实体的方法 几乎免费。异步方法并非如此


阅读它以了解更多细节

事实上,在非常高的迭代次数下,时间几乎相同,这可能意味着较低迭代次数的差异是基于噪音、GC集合、上下文切换和基准测试框架的其他错误。还要注意的是,
DateTime。现在,
并没有足够的精度来测量这么短的时间。对执行那么快的代码片段进行基准测试真的很难。从本质上讲,你的测试实际上并没有说任何有意义的事情;错误幅度如此之大,以至于结果实际上毫无意义。值得注意的是,您的第一个方法非常简单,编译器可能会对其进行优化。它甚至可能同步运行(我知道使用WPF
Dispatcher
类,后台作业可能运行得太快,以至于调用方在异步请求返回之前就将其视为已完成)。正如@Servy所建议的,在这些条件下,您的测试将不会真正有意义。@DanPuzey,不带(或直到)
wait
async
-ed方法将同步运行。但是,如果不返回用于包装返回结果的任务,则无法运行它。我相信使用
async
的ppl在不伤脑筋的情况下正确理解了我所写的内容,如何在更长的篇幅内写得不那么含糊不清
Repeat 1000000 times.
UsingAsyncModifier: 00:00:00.8458490
UsingTaskCompletionSource: 00:00:00.8870980
UsingTaskFromResult: 00:00:00.9027320
Repeat 1000000 times.
UsingAsyncModifier: 5458
UsingTaskCompletionSource: 2838
UsingTaskFromResult: 2556
class Program
{
     public static async Task<int> UsingAsyncModifier()
    {
        return 10;
    }

    public static Task<int> UsingTaskCompletionSource()
    {
        TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
        tcs.SetResult(10);
        return tcs.Task;
    }
    public static Task<int> UsingTaskFromResult()
    {
        return TaskEx.FromResult(10);
    }
    static void Main(string[] args)
    {
      //DateTime t = DateTime.Now;
      Stopwatch timer = new Stopwatch();
      const int repeat = 1000*1000; // Results volatile while repeat grows.
      Console.WriteLine("Repeat {0} times.", repeat);

        int j = 0;
        //DateTime t = DateTime.Now;
        timer.Start();
        for (int i = 0; i < repeat; i++)
        {
            j += UsingAsyncModifier().Result;
        }
        timer.Stop();
        Console.WriteLine("UsingAsyncModifier: {0}"
                          , timer.ElapsedMilliseconds);
        //t = DateTime.Now;
        timer.Reset();

        j = 0;

        timer.Start();
        for (int i = 0; i < repeat; i++)
        {
            j += UsingTaskCompletionSource().Result;
        }
        timer.Stop();
        Console.WriteLine("UsingTaskCompletionSource: {0}"
                           , timer.ElapsedMilliseconds);
        //t = DateTime.Now;
        timer.Reset();
        j = 0;
        timer.Start();
        for (int i = 0; i < repeat; i++)
        {
          j += UsingTaskFromResult().Result;
        }
        timer.Stop();
        Console.WriteLine("UsingTaskFromResult: {0}"
                          , timer.ElapsedMilliseconds);

        Console.ReadLine();
    }
}