首页 > 解决方案 > C#中Async Await编程的基本理解

问题描述

我试图理解Async/Await编程模型。我写了一个示例程序来理解这一点。

我已经编写了 3 个独立的异步方法,名为GetFirstValue, GetSecondValue, GetThirdValue. 有一个名为的方法M1,它异步执行上述 3 个方法,并返回上述 3 个方法的连接结果。

我的主要想法是,如果方法GetFirstValue需要 5 秒,GetSecondValue需要 7 秒和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;
        }
    }
}

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

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;
        }
    }
}

标签: c#.netmultithreadingasync-await

解决方案


问题是您正在以Get伪异步方式运行该方法。在调用then之前,您的调用GetFirstValue和 await 函数完成。GetSecondValueGetThirdValue

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

// 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;

或者,您可以删除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;

推荐阅读