在 C# 中使用异步、等待、任务进行异步编程
本文关键字:异步 任务 编程 等待 | 更新日期: 2023-09-19 09:02:01
C#和.NET Framework(4.5和Core)支持使用一些本机函数,类和保留关键字进行异步编程。
在了解什么是异步编程之前,让我们使用以下控制台示例了解什么是同步编程。
示例: Asynchronous Program
static void Main(string[] args)
{
LongProcess();
ShortProcess();
}
static void LongProcess()
{
Console.WriteLine("LongProcess Started");
//some code that takes long execution time
System.Threading.Thread.Sleep(4000); // hold execution for 4 seconds
Console.WriteLine("LongProcess Completed");
}
static void ShortProcess() {
Console.WriteLine("ShortProcess Started");
//do something here
Console.WriteLine("ShortProcess Completed");
}
Output:
LongProcess Started
LongProcess Completed
ShortProcess Started
ShortProcess Completed
在上面的示例中,LongProcess()
方法是一些长时间运行的任务,例如从服务器读取文件、调用返回大量数据的 Web API 或上传或下载大文件。
执行需要更长的时间(Thread.Sleep(4000)
保持它 4 秒只是为了显示较长的执行时间)。ShortProcess()
是一种在 LongProcess()
方法之后执行的简单方法。
上述程序同步执行。这意味着执行从Main()
方法开始,其中它首先执行LongProcess()
方法,然后执行ShortProcess()
方法。在执行过程中,应用程序被阻止并变得无响应(您主要可以在基于 Windows 的应用程序中看到这一点)。这称为同步编程,在当前行完全执行之前,执行不会转到下一行。
什么是异步编程?(What is Asynchronous Programming?)
在异步编程中,代码在线程中执行,而不必等待 I/O 绑定或长时间运行的任务完成。例如,在异步编程模型中,LongProcess()
方法将在与线程池不同的线程中执行,主应用程序线程将继续执行下一条语句。
Microsoft建议Task-based Asynchronous Pattern使用async、await关键字和Task或Task<TResult>类在.NET Framework或.NET Core应用程序中实现异步编程。
现在让我们使用 async
关键字以异步模式重写上面的示例。
示例: Asynchronous Program
static async Task Main(string[] args)
{
LongProcess();
ShortProcess();
}
static async void LongProcess()
{
Console.WriteLine("LongProcess Started");
await Task.Delay(4000); // hold execution for 4 seconds
Console.WriteLine("LongProcess Completed");
}
static void ShortProcess() {
Console.WriteLine("ShortProcess Started");
//do something here
Console.WriteLine("ShortProcess Completed");
}
Output:
LongProcess Started
ShortProcess Started
ShortProcess Completed
LongProcess Completed
在上面的示例中,Main()
方法由 async
关键字标记,返回类型为 Task
。async
关键字将该方法标记为异步。请注意,必须async
方法链中的所有方法才能实现异步编程。因此,必须async
Main()
方法才能使子方法异步。
LongProcess()
方法还标有 async
关键字,使其异步。
await Task.Delay(4000);
将线程执行保持 4 秒。
现在,程序从主应用程序线程中的async Main()
方法开始执行。async LongProcess()
方法在单独的线程中执行,主应用程序线程继续执行下一个语句,该语句调用ShortProcess()
该方法并且不等待LongProcess()
完成。
异步、等待和任务(async, await, and Task)
如果 async
方法将值返回给调用代码,请将async
与 await
一起使用并Task
。我们在上面的程序中只使用了 async
关键字来演示简单的异步 void 方法。
await
关键字等待 async
方法,直到它返回值。因此,主应用程序线程会停在那里,直到收到返回值。
Task类表示异步操作,泛型类表示Task<TResult>可以返回值的操作。
在上面的示例中,我们使用了启动async
操作的await Task.Delay(4000)
,该操作休眠 4 秒,等待将线程保留到 4 秒。
下面演示返回值的 async
方法。
示例: Async Method Returns Value
static async Task Main(string[] args)
{
Task<int> result = LongProcess();
ShortProcess();
var val = await result; // wait untile get the return value
Console.WriteLine("Result: {0}", val);
Console.ReadKey();
}
static async Task<int> LongProcess()
{
Console.WriteLine("LongProcess Started");
await Task.Delay(4000); // hold execution for 4 seconds
Console.WriteLine("LongProcess Completed");
return 10;
}
static void ShortProcess()
{
Console.WriteLine("ShortProcess Started");
//do something here
Console.WriteLine("ShortProcess Completed");
}
Output:
LongProcess Started
ShortProcess Started
ShortProcess Completed
LongProcess Completed
Result: 10
在上面的示例中,在静态async Task<int> LongProcess()
方法中,Task<int>
用于指示返回值类型 int。 int val = await result;
将在那里停止主线程,直到它获得结果中填充的返回值。
一旦获得 result
变量中的值,它就会自动将一个整数分配给 val
。
async
方法应返回 void
、 Task
或 Task<TResult>
,其中 TResult
是 async
方法的返回类型。
返回void
通常用于事件处理程序。async
关键字允许我们在方法中使用 await 关键字,以便我们可以等待异步方法完成依赖于返回值的其他方法。
如果您有多个返回值的async
方法,则可以在后续步骤中使用返回值之前对所有方法使用 await
。
示例: Async Methods
static async Task Main(string[] args)
{
Task<int> result1 = LongProcess1();
Task<int> result2 = LongProcess2();
//do something here
Console.WriteLine("After two long processes.");
int val = await result1; // wait untile get the return value
DisplayResult(val);
val = await result2; // wait untile get the return value
DisplayResult(val);
Console.ReadKey();
}
static async Task<int> LongProcess1()
{
Console.WriteLine("LongProcess 1 Started");
await Task.Delay(4000); // hold execution for 4 seconds
Console.WriteLine("LongProcess 1 Completed");
return 10;
}
static async Task<int> LongProcess2()
{
Console.WriteLine("LongProcess 2 Started");
await Task.Delay(4000); // hold execution for 4 seconds
Console.WriteLine("LongProcess 2 Completed");
return 20;
}
static void DisplayResult(int val)
{
Console.WriteLine(val);
}
Output:
LongProcess 1 Started
LongProcess 2 Started
After two long processes.
LongProcess 2 Completed
LongProcess 1 Completed
10
20
在上面的程序中,我们确实等待结果 1 并等待结果 2,就在我们需要将返回值传递给另一个方法之前。
因此,您可以使用 async
、await 和 Task 在 .NET Framework 或 .NET Core 中使用 C# 实现异步编程。
本文内容总结: