Dispose和Finalize是运行的 .NET 和 .NET Core 应用程序释放占用的资源的两种方法。通常,如果应用程序中有非托管资源,应该显式地释放这些资源占用的资源。
由于 Finalize的非确定性,以及在性能方面的成本很高,因此 Dispose方法的使用频率远高于 Finalize。其实,我们可以在一个实现了 IDisposable接口的类型上使用 Dispose方法。
本文中提供的代码示例均默认运行在 Visual Studio 2022。
使用 VS2022 创建 ASP.NET Core 项目
我们在 Visual Studio 2022 中创建一个 ASP.NET Core 项目。按照以下步骤在 Visual Studio 2022 中创建一个新的 ASP.NET Core Web API 6 项目。
- 1) 启动 Visual Studio 2022 IDE。
- 2) 单击 “Create new project”。
- 3) 在 “Create new project” 窗口中,从显示的模板列表中选择 “ASP.NET Core Web API”。
- 4) 点击下一步。
- 5) 在 “Configure your new project” 窗口中,指定新项目的名称和位置。
- 6) 根据您的偏好,可选择选中 “Place solution and project in the same directory” 复选框。
- 7) 点击下一步。
- 8) 在接下来显示的 “Additional Information” 窗口中,从顶部的下拉列表中选择 .NET 6.0 作为目标框架。将 “Authentication Type” 保留为 “None”(默认)。确保选中 “Use controllers ...” 选项。
- 9) 确保未选中 “Enable Docker,”、“Configure for HTTPS” 和 “Enable Open API Support” 复选框,因为我们不会在此处使用任何这些功能。您也可以选择取消选中 “Use controllers(取消选中以使用最少的 API)” 复选框,因为我们将创建自己的控制器。
- 10) 单击创建。
这将在 Visual Studio 2022 中创建一个新的 ASP.NET Core 6 Web API 项目。我们将在本文的后续部分中使用该项目来说明 Dispose的用法。
1. 创建一个实现 IDisposable 接口的类
我们现在将创建一个实现 IDisposable接口的类,代码如下:
public class FileManager: IDisposable {
FileStream fileStream = new FileStream(@"C:\Test.txt",
FileMode.Append);
public async Task Write(string text) {
byte[] buffer = Encoding.Unicode.GetBytes(text);
int offset = 0;
try {
await fileStream.WriteAsync(buffer, offset,
buffer.Length);
}
catch {
//Write code here to handle exceptions.
}
}
public void Dispose() {
if (fileStream != null) {
fileStream.Dispose();
}
}
}
FileManager类实现 IDisposable接口并包含两个方法:Write和 Dispose。前者用于将文本异步写入文件,后者用于通过调用 FileStream类的 Dispose方法从内存中删除 FileStream实例。
下面,我们介绍在 ASP.NET Core 6 中处理 IDisposable对象的四种方法。
2. 使用 “using” 语句处理 IDisposable 对象
处理 IDisposable实例的最简单方法是使用“using”语句,它会自动调用实例上的 Dispose方法。以下代码片段说明了这一点。
using(FileManager fileManager = new FileManager())
{
await fileManager.Write("This is a text");
}
3. 在请求结束时处理 IDisposable 对象
在 ASP.NET Core 或 ASP.NET Core MVC 应用程序中工作时,我们可能经常需要在 HTTP 请求结束时处理对象。
HttpResponse.RegisterForDispose方法可用于以这种方式注册 IDisposable对象以进行处理。它接受实现 IDisposable接口的类的实例,并确保作为参数传递给它的 IDisposable对象随每个请求自动处理。
以下代码演示了如何使用 HttpResponse.RegisterForDispose 方法在每个 HTTP 请求结束时注册 FileManager类的实例。
public class DefaultController: ControllerBase {
readonly IDisposable _disposable;
public DefaultController() {
_disposable = new FileManager();
}
}
4. 使用内置的 IoC 容器处理 IDisposable 对象
另一种自动处理 IDisposable对象的方法是使用 ASP.NET Core 中的内置 IoC(控制反转)容器。您可以利用 Transient、Scoped或 Singleton实例来创建服务并将它们添加到内置 IoC 容器中。
将 IDisposable对象添加到 Startup类的 ConfigureServices方法中的 IoC 容器,以便这些对象随每个 HTTP 请求自动处理。
5. 使用 IHostApplicationLifetime 事件处理 IDependency 对象
ASP.NET Core 有一个名为 IHostApplicationLifetime的接口,允许您在应用程序启动或关闭时运行自定义代码。您可以利用此接口的 Register方法来注册事件。
Startup类的 Configure方法可以接受以下参数:
- IApplicationBuilder
- IHostingEnvironment
- ILoggerFactory
- IHostApplicationLifetime
以下代码演示了如何使用 IHostApplicationLifetime接口注册对象以在应用程序关闭时进行处置。
public void Configure(IApplicationBuilder app, IHostApplicationLifetime hostApplicationLifetime) {
hostApplicationLifetime.ApplicationStopping.Register(OnShutdown);
}
private void OnShutdown() {
// 释放对象的代码
}
最后,ASP.NET Core 6 中默认不会创建 Startup.cs。我们需要手动创建一个,然后在 Program.cs 文件中编写以下代码以指定您将在其中使用的 Startup 类应用程序。
var builder = WebApplication.CreateBuilder(args);
builder.Host.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
using var app = builder.Build();
app.Run();
与 Finalize 不同,我们显式使用 Dispose 方法来释放非托管资源。您应该在实现它的任何对象上显式调用 Dispose 方法,以释放该对象可能持有其引用的任何非托管资源。
参考资料:
1. C#教程
2. 编程宝库
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易盾网络。
