理解C#中的Async和Await是如何线程成为时间管理大师
什么是异步编程
异步编程是为了提高程序的性能和相应性能。在异步编程中,任务呗分解成可以独立执行的子任务,使得程序能够在等待城市间操作完成的同时,继续执行其他任务,而不会阻塞线程或进程。
同步编程中程序会按照顺序实行,当遇到耗时操作时(如文件,网络请求,数据库查询等I/O操作),当前线程会阻塞直到操作完成。这种阻塞式得操作会导致程序响应速度速度变慢,并且浪费了资源。
异步编程通过以下方式解决这个问题:
- 非阻塞调用:异步不会阻塞主线程或进程,在后台执行允许程序继续执行其他任务。
- 回调机制:异步操作通常会提供回调函数,用于在操作完成时通知调用者。这样可以操作完成后执行特定得代码逻辑,而不必等待操作完成。
- 事件循环: 在异步编程中通常使用事件循环机制来管理异步任务的执行顺序和状态。事件循环持续监听事件并处理它们,使得程序能够在事件发生时响应。
- 提高并发性: 异步编程可以更好地利用系统资源,提高程序并发性和吞吐量。通过将耗时地操作放入后台执行,可以同时处理多个任务,从而提高程序地性能。
IO操作通常由操作只需要线程发起请求,剩下地由操作系统或者IO线程来操作。对于有IO操作的方法使用异步可以有效地提升系统执行地效率。
async await
async 和 await 关键字提供了简洁的方法来处理异步操作,使得代码既简洁又易于维护。
async 关键字用于声明异步办法,表明该方法包含异步操作。它本身不创建新线程。
async 必须与Task Task void使用。当异步方法不需要返回值并且不需要登台完成时使用 async void 可以简化方法的调用和使用 列如button地按钮事件处理。无法进行异常处理,难以调试。导致结果不可预测。
await 关键字用于等待异步操作完成。同时控制权(当前线程的执行流程)会返回给方法地调用者。
ConfigureAwait
用于配置异步操作的上下文行为,默认为true。默认情况下异步操作会在调用它的线程上执行。可以使用ConfigreAwait(false)让线程不用回到之前的线程以提高性能。
using System.Diagnostics;
Task.Run(async() =>{
Stopwatch stopwatch = Stopwatch.StartNew();
stopwatch.Start();
Console.WriteLine("异步执行开始!");
for (var i = 0; i < 100; i++)
{
await Stop5(i);
}
stopwatch.Stop();
TimeSpan elapsedTime = stopwatch.Elapsed;
Console.WriteLine($"异步执行完成运行时间{elapsedTime.ToString()}");
});
Task.Run(async () => {
Stopwatch stopwatch = Stopwatch.StartNew();
stopwatch.Start();
Console.WriteLine("ConfigureAwait异步执行开始!");
for (var i = 0; i < 100; i++)
{
await Stop5(i).ConfigureAwait(false);
}
stopwatch.Stop();
TimeSpan elapsedTime = stopwatch.Elapsed;
Console.WriteLine($"ConfigureAwait异步执行完成运行时间{elapsedTime.ToString()}");
});
Console.ReadLine();
async Task Stop5(int i)
{
Thread.Sleep(10);
}
异步执行开始!
ConfigureAwait异步执行开始!
异步执行完成运行时间00:00:01.5907243
ConfigureAwait异步执行完成运行时间00:00:01.5907191
可以看到ConfigureAwait(false)明显地速度提升。
实际应用中Asp.Net 项目 效果能得到提升。Winform WPF项目中会影响UI线程。WPF Winform受到SynchronizationContext的影响 ,它负责管理线程之间的上下文,确保特定代码在正确的线程上执行