查看原文
其他

.NET 6 新特性Controller支持 IAsyncDisposable

My IO DotNet 2022-07-19

前言


.NET中拥有非托管资源的类通常会实现IDisposable接口,以提供一种同步释放非托管资源的机制。但是,在某些情况下,需要提供一种异步机制来释放非托管资源,这时候可以实现IAsyncDisposable接口。


在实现此接口后,将使用DisposeAsync方法来释放这些非托管资源。但是在.NET 6之前,即使Controller实现了IAsyncDisposable接口,也不会执行DisposeAsync方法。


下面,让我们来验证一下。


示例


1、.NET 5.0


使用VS 2019创建基于.NET 5.0框架的Web API项目,然后修改WeatherForecastController代码,实现IAsyncDisposable接口:

public class WeatherForecastController : ControllerBaseIAsyncDisposable
{
    [ApiExplorerSettings(IgnoreApi = true)]
    public ValueTask DisposeAsync()
    {
        throw new NotImplementedException();
    }
}public class WeatherForecastController : ControllerBaseIAsyncDisposable
{
    [ApiExplorerSettings(IgnoreApi = true)]
    public async ValueTask DisposeAsync()
    {
        _logger.LogInformation($"{DateTime.Now} Begin DisposeAsync");
        await Task.Delay(3000);//模拟异步释放非托管资源
        _logger.LogInformation($"{DateTime.Now} End DisposeAsync");
    }
}

加上ApiExplorerSettings是为了避免swagger报错。执行请求,发现并没有抛出异常,说明没有执行DisposeAsync方法。而当我们实现IDisposable接口后,再次执行请求,会执行Dispose方法抛出异常,说明Controller确实被释放了:

2、.NET 6.0

使用VS 2022创建基于.NET 6.0框架的Web API项目,然后修改WeatherForecastController代码,实现IAsyncDisposable接口:

public class WeatherForecastController : ControllerBaseIAsyncDisposable
{
    [ApiExplorerSettings(IgnoreApi = true)]
    public async ValueTask DisposeAsync()
    {
        _logger.LogInformation($"{DateTime.Now} Begin DisposeAsync");
        await Task.Delay(3000);//模拟异步释放非托管资源
        _logger.LogInformation($"{DateTime.Now} End DisposeAsync");
    }
}

运行效果如下,执行了DisposeAsync方法:

总结

最好同时实现IDisposable和IAsyncDisposable接口,确保释放资源:

[ApiExplorerSettings(IgnoreApi = true)]  
public void Dispose()  
{  
    _logger.LogInformation($"{DateTime.Now} Begin Dispose");  
    Dispose(disposing: true);  
    _logger.LogInformation($"{DateTime.Now} End Dispose");  
}  
  
[ApiExplorerSettings(IgnoreApi = true)]  
public async ValueTask DisposeAsync()  
{  
    _logger.LogInformation($"{DateTime.Now} Begin DisposeAsync");  
    await Task.Delay(3000);//模拟异步释放非托管资源  
  
    Dispose(disposing: false);  
    _logger.LogInformation($"{DateTime.Now} End DisposeAsync");  
}  
  
protected void Dispose(bool disposing)  
{  
    if (disposing)  
    {  
        Thread.Sleep(3000);//模拟同步释放非托管资源  
    }  
    _logger.LogInformation($"{DateTime.Now} Dispose {disposing}");  
}  


- EOF -

推荐阅读  点击标题可跳转
既生瑜何生亮 access_token VS refresh_token改用 VS Code 开发 ASP.NET Core 心得.NET Core +Kubernetes 在互联网公司的落地实践

看完本文有收获?请转发分享给更多人

推荐关注「DotNet」,提升.Net技能 

点赞和在看就是最大的支持❤️

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存