发布于2026-07-23 阅读(0)
扫一扫,手机访问
在 .NET 的世界里,async 和 await 这两个关键字可以说是异步编程的门面担当。async 用来标记一个方法是异步方法,里面可以藏着多个 await 表达式;而 await 呢,就是专门在异步方法里等待某个任务(Task 或 Taskawait 时,当前方法会暂停,但主线程并不会傻等着——它会转身去干别的事,等那个任务完成了再回来继续跑剩下的代码。
那同步和异步到底怎么区分?
异步最大的好处就是非阻塞——调用线程不会停下来干等子线程完成。所以,那些不急着要结果、但是很耗时的任务,完全可以扔到异步里去跑,整个程序的效率自然就上来了。
举个直观的例子:主线程要依次执行 5 个方法,耗时分别是 0.1s、0.2s、0.3s、0.4s、0.5s。如果用同步的方式,主线程得老老实实一个一个串着跑,总时间就是 1.5 秒。但如果把这些方法都改成异步的,主线程大概只需要 0.5 秒就能搞定。
原因很简单:同步就像一根线穿五颗珠子,一颗穿完才能穿下一颗,总时间就是所有珠子时间之和。异步呢,相当于五个人每人拿一根线同时穿一颗珠子,总时间取决于最慢的那颗珠子——0.5 秒。因为主线程调用异步方法时,不会一头扎进去执行,而是在遇到 await 后立刻返回一个 Task,这个 Task 会在子线程里慢慢跑,主线程则继续往后走,去调用下一个方法。
那问题来了:主线程跑得飞快,异步方法的结果怎么收回来?常见的方式有这么几种:
1. 直接用 await 等待
public class Demo
{
public async Task DemoAsync()
{
await Task.Delay(1000);
Console.WriteLine("1秒后执行");
}
}
public Class Program
{
static async Task Main(string[] args)
{
Demo demo = new Demo();
// 使用 await 等待DemoAsync的执行
await demo.DemoAsync();
Console.ReadKey();
}
}
2. 使用事件通知
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
demo.OnEvent += (() =>
{
Console.WriteLine("事件订阅");
});
demo.DemoAsync();
Console.ReadKey();
}
}
public class Demo
{
public event Action OnEvent;
public async Task DemoAsync()
{
Console.WriteLine("开始执行");
await Task.Delay(1000);
Console.WriteLine("1秒后执行");
OnEvent?.Invoke();
}
}
3. 回调函数
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
demo.DemoAsync(() =>
{
Console.WriteLine("回调函数");
});
Console.ReadKey();
}
}
public class Demo
{
public async Task DemoAsync(Action callback)
{
Console.WriteLine("开始执行");
await Task.Delay(1000);
callback?.Invoke();
Console.WriteLine("1秒后执行");
}
}
4. 只启动异步操作,不等待结果
如果只是启动一个异步任务,根本不需要它的返回值,那就直接调用,不用加
await。主线程不会被阻塞,也不会去管结果。
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
demo.DemoAsync();
Console.ReadKey();
}
}
public class Demo
{
public async Task DemoAsync()
{
Console.WriteLine("开始执行");
await Task.Delay(1000);
Console.WriteLine("1秒后执行");
}
}
5. 把异步结果存到变量里,后面再取
如果想在某个时刻拿到异步结果,但又不想立刻等它完成,可以先把返回的 Task 存起来,等需要的时候再用
Wait()或.Result来取。
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
var demoResult = demo.DemoAsync();
// 使用 wait等待异步的完成
demoResult.Wait();
if (demoResult.IsCompleted)
{
Console.WriteLine("str执行完成");
Console.WriteLine(demoResult.Result);
}
Console.ReadKey();
}
}
public class Demo
{
public async Task DemoAsync()
{
Console.WriteLine("开始执行");
await Task.Delay(1000);
Console.WriteLine("1秒后执行");
return "异步返回结果";
}
}
async 和 await 可以避免那些长时间运行的操作(比如 IO 操作)把主线程卡死,应用程序的反应自然更快了。异步的效果会沿着调用链一路向上传染。你调了个异步方法,那调用它的方法也得变成异步,而且返回类型还得改成 Task 或 Task
那怎么避免这种“强制传染”呢?有几种思路:
await,这样调用者就不用变成异步方法了。Task.Run 会新起一个任务去跑异步逻辑,从而切断了传递性。await 更灵活,也不会逼迫上层变成异步。Wait() 或访问 .Result,虽然不优雅但确实能避开传递性。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8