c# - C#中Async Await编程的基本理解
问题描述
我试图理解Async/Await
编程模型。我写了一个示例程序来理解这一点。
我已经编写了 3 个独立的异步方法,名为GetFirstValue
, GetSecondValue
, GetThirdValue
. 有一个名为的方法M1
,它异步执行上述 3 个方法,并返回上述 3 个方法的连接结果。
我的主要想法是,如果方法GetFirstValue
需要 5 秒,GetSecondValue
需要 7 秒和GetThirdValue
8 秒。然后,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;
}
}
}
解决方案
问题是您正在以Get
伪异步方式运行该方法。在调用then之前,您的调用GetFirstValue
和 await 函数完成。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;
或者,您可以删除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;
推荐阅读
- android - 从其他片段更改 ViewPager 的当前片段
- r - 我们可以在 R Shiny 中跟踪系统日志记录和系统注销时间吗
- amazon-rds - 在新版本 @aws-cdk/aws-secretsmanager: 1.20.0 中,secretsmanager.AttachmentTargetType 的替代方案是什么?
- python - 是否存在操作员错误,因为执行后它说的是模棱两可的错误。我在做什么错误?
- c# - 检索具有 CLSID {00024500-0000-0000-C000-000000000046} 的组件的 COM 类工厂失败 - 80080005
- typescript - 如何将 keyof T 限制为字符串键?
- android - 如何删除单例数据?
- cygwin - Gtk-WARNING **:无法打开显示:export DISPLAY=localhost:0.0 Windows 10 Cygwin
- data-structures - 使用 CL_ABAP_CORRESPONDING 映射结构中不同级别的字段
- java - 从两个方向向量获取欧拉旋转