前两天碰到一个数据库异常引发的程序崩溃,对这个问题很感兴趣,因为开发这么多年了,还没有碰到bug引发程序崩溃的问题,但是也有点想不明白,列表的ForEach怎么会让程序崩溃呢。贴上没有业务的代码:
[HttpGet]
public string GetStr()
{
List<int> s = new List<int>() {
0 };
s.ForEach(async (x) =>
{
await Task.Run(() =>
{
throw new Exception("数据库异常");
});
});
return "111";
}
就是这段代码,在网上找资料没找到相关的问题,但是找到了同步调异步方法会导致程序崩溃 async void 导致程序崩溃,
看了这篇文章也调试了对应代码确实是会让程序崩溃,但是我这里用的是ForEach里面崩溃,这有什么关联呢,后面才反应过来,List.ForEach这个方法里面返回的void,里面有方法是异步的就加了await和async,无形之中就成了async void ,刚好数据库有异常就崩溃了。
这里面也还有一个问题就是如下代码也会崩溃:
[HttpGet]
public async void Get()
{
//异常会导致程序崩溃
throw new Exception("ex!");
}
这里并没有像正常的使用await和async,而是只有一个async,看来还需要进一步理解 async关键字。
当你使用 async void 方法时,异常会直接传播到调用代码的上层,而不是通过 Task 或 Task 对象来捕获。这可能会导致无法正确捕获和处理异常,进而导致程序崩溃。另外,async void 方法在异步操作完成时无法通过 await 关键字等待其完成,这可能导致在异步操作完成之前就继续执行后续代码,从而导致意外的行为或错误。
async void方法抛出的异常无法被捕获,异常会被一直往上面抛,最终在AppDomain层级被捕获,然后程序就挂了。