对C#中的Async Await编程的基本了解

San*_*wah -1 .net c# multithreading async-await

我试图了解Async/Await编程模型。我编写了一个示例程序来了解相同的内容。

我已经写了一个名为3种独立的异步方法GetFirstValueGetSecondValueGetThirdValue。有一种名为的方法M1,该方法异步执行上述3种方法,并返回上述3种方法的串联结果。

我的主要想法是,如果方法GetFirstValue需要5秒钟,GetSecondValue7秒钟和GetThirdValue8秒钟。然后,M1应在不到20秒的时间内返回。由于3种方法不同步。

但是由于我没有正确理解这个概念。我做错了。这是我正在研究的完整程序。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LearningAsyncProgramming
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();

            AsyncMethodsClass asyncMethods = new AsyncMethodsClass();
            Console.WriteLine(asyncMethods.M1().Result);
            watch.Stop();

            Console.WriteLine(watch.ElapsedMilliseconds/1000);
        }
    }

    class AsyncMethodsClass
    {
        public async Task<string> M1()
        {
            string retVal = string.Empty;

            int v1 = await GetFirstValue();
            int v2 = await GetSecondValue();
            int v3 = await GetThirdValue();

            return string.Concat( v1,"-",v2,"-",v3);
        }

        private async Task<int> GetFirstValue()
        {
            int a = await GetTimer();
            return a;
        }
        private async Task<int> GetSecondValue()
        {
            int a = await GetTimer();
            return a;
        }
        private async Task<int> GetThirdValue()
        {
            int a = await GetTimer();
            return a;
        }

        private async Task<int> GetTimer()
        {
            int someNumber = new Random().Next(5,9);

            Thread.Sleep(someNumber * 1000);
            return someNumber;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是实施答案中的建议之后的更新代码。它完全符合我的期望。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LearningAsyncProgramming
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();

            AsyncMethodsClass asyncMethods = new AsyncMethodsClass();
            Console.WriteLine(asyncMethods.M1().Result);
            watch.Stop();

            Console.WriteLine(watch.ElapsedMilliseconds/1000);
        }
    }

    class AsyncMethodsClass
    {
        public async Task<string> M1()
        {
            // Start all the functions, but don't wait just yet
            var t1 = GetFirstValue();
            var t2 = GetSecondValue();
            var t3 = GetThirdValue();

            return string.Concat( await t1,"-",await t2,"-",await t3);
        }

        private async Task<int> GetFirstValue()
        {
            int a = await GetTimer();
            return a;
        }
        private async Task<int> GetSecondValue()
        {
            int a = await GetTimer();
            return a;
        }
        private async Task<int> GetThirdValue()
        {
            int a = await GetTimer();
            return a;
        }

        private async Task<int> GetTimer()
        {
            int someNumber = new Random().Next(5,9);

            await Task.Delay(someNumber * 1000);
            return someNumber;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sea*_*ean 5

问题是您正在Get伪异步地运行该方法。调用GetFirstValue并等待函数完成GetSecondValue,然后再调用GetThirdValue

您要做的是并行运行它们,然后等待它们全部完成:

// Start all the functions, but don't wait just yet
var t1 = GetFirstValue();
var t2 = GetSecondValue();
var t3 = GetThirdValue();

// Wait for them all to complete in parallel
await Task.WhenAll(t1, t2, t3);

// Get the results from the task
int v1 = t1.Result;
int v2 = t2.Result;
int v3 = t3.Result;
Run Code Online (Sandbox Code Playgroud)

或者,您可以删除WhenAll和等待各个任务。因为他们现在都在运行,所以基本上是相同的:

// Start all the functions, but don't wait just yet
var t1 = GetFirstValue();
var t2 = GetSecondValue();
var t3 = GetThirdValue();

// All the tasks are running, so get the results from the task
int v1 = await t1;
int v2 = await t2;
int v3 = await t3;
Run Code Online (Sandbox Code Playgroud)