Dispose 和 Finalize 是運(yùn)行的 .NET 和 .NET Core 應(yīng)用程序釋放占用的資源的兩種方法。通常,如果應(yīng)用程序中有非托管資源,應(yīng)該顯式地釋放這些資源占用的資源。
由于 Finalize 的非確定性,以及在性能方面的成本很高,因此 Dispose 方法的使用頻率遠(yuǎn)高于 Finalize。其實(shí),我們可以在一個(gè)實(shí)現(xiàn)了 IDisposable 接口的類(lèi)型上使用 Dispose 方法。
本文中提供的代碼示例均默認(rèn)運(yùn)行在 Visual Studio 2022。
?
1. 使用 VS2022 創(chuàng)建 ASP.NET Core 項(xiàng)目
我們?cè)?Visual Studio 2022 中創(chuàng)建一個(gè) ASP.NET Core 項(xiàng)目。按照以下步驟在 Visual Studio 2022 中創(chuàng)建一個(gè)新的 ASP.NET Core Web API 6 項(xiàng)目。
- 1) 啟動(dòng) Visual Studio 2022 IDE。
- 2) 單擊 “Create new project”。
- 3) 在 “Create new project” 窗口中,從顯示的模板列表中選擇 “ASP.NET Core Web API”。
- 4) 點(diǎn)擊下一步。
- 5) 在 “Configure your new project” 窗口中,指定新項(xiàng)目的名稱(chēng)和位置。
- 6) 根據(jù)您的偏好,可選擇選中 “Place solution and project in the same directory” 復(fù)選框。
- 7) 點(diǎn)擊下一步。
- 8) 在接下來(lái)顯示的 “Additional Information” 窗口中,從頂部的下拉列表中選擇 .NET 6.0 作為目標(biāo)框架。將 “Authentication Type” 保留為 “None”(默認(rèn))。確保選中 “Use controllers ...” 選項(xiàng)。
- 9) 確保未選中 “Enable Docker,”、“Configure for HTTPS” 和 “Enable Open API Support” 復(fù)選框,因?yàn)槲覀儾粫?huì)在此處使用任何這些功能。您也可以選擇取消選中 “Use controllers(取消選中以使用最少的 API)” 復(fù)選框,因?yàn)槲覀儗?chuàng)建自己的控制器。
- 10) 單擊創(chuàng)建。
這將在 Visual Studio 2022 中創(chuàng)建一個(gè)新的 ASP.NET Core 6 Web API 項(xiàng)目。我們將在本文的后續(xù)部分中使用該項(xiàng)目來(lái)說(shuō)明 Dispose 的用法。
1. 創(chuàng)建一個(gè)實(shí)現(xiàn) IDisposable 接口的類(lèi)
我們現(xiàn)在將創(chuàng)建一個(gè)實(shí)現(xiàn) IDisposable 接口的類(lèi),代碼如下:??
??
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 類(lèi)實(shí)現(xiàn) IDisposable 接口并包含兩個(gè)方法:Write 和 Dispose。前者用于將文本異步寫(xiě)入文件,后者用于通過(guò)調(diào)用 FileStream 類(lèi)的 Dispose 方法從內(nèi)存中刪除 FileStream 實(shí)例。
下面,我們介紹在 ASP.NET Core 6 中處理 IDisposable 對(duì)象的四種方法。
?
2. 使用 “using” 語(yǔ)句處理 IDisposable 對(duì)象
處理 IDisposable 實(shí)例的最簡(jiǎn)單方法是使用“using”語(yǔ)句,它會(huì)自動(dòng)調(diào)用實(shí)例上的 Dispose 方法。以下代碼片段說(shuō)明了這一點(diǎn)。
using(FileManager fileManager = new FileManager())
{
await fileManager.Write("This is a text");
}
?
3. 在請(qǐng)求結(jié)束時(shí)處理 IDisposable 對(duì)象
在 ASP.NET Core 或 ASP.NET Core MVC 應(yīng)用程序中工作時(shí),我們可能經(jīng)常需要在 HTTP 請(qǐng)求結(jié)束時(shí)處理對(duì)象。
HttpResponse.RegisterForDispose 方法可用于以這種方式注冊(cè) IDisposable 對(duì)象以進(jìn)行處理。它接受實(shí)現(xiàn) IDisposable 接口的類(lèi)的實(shí)例,并確保作為參數(shù)傳遞給它的 IDisposable 對(duì)象隨每個(gè)請(qǐng)求自動(dòng)處理。
以下代碼演示了如何使用 HttpResponse.RegisterForDispose 方法在每個(gè) HTTP 請(qǐng)求結(jié)束時(shí)注冊(cè) FileManager 類(lèi)的實(shí)例。??
??
public class DefaultController: ControllerBase {
readonly IDisposable _disposable;
public DefaultController() {
_disposable = new FileManager();
}
}
?
4. 使用內(nèi)置的 IoC 容器處理 IDisposable 對(duì)象
另一種自動(dòng)處理 IDisposable 對(duì)象的方法是使用 ASP.NET Core 中的內(nèi)置 IoC(控制反轉(zhuǎn))容器。您可以利用 Transient、Scoped 或 Singleton 實(shí)例來(lái)創(chuàng)建服務(wù)并將它們添加到內(nèi)置 IoC 容器中。
將 IDisposable 對(duì)象添加到 Startup 類(lèi)的 ConfigureServices 方法中的 IoC 容器,以便這些對(duì)象隨每個(gè) HTTP 請(qǐng)求自動(dòng)處理。
5. 使用 IHostApplicationLifetime 事件處理 IDependency 對(duì)象
ASP.NET Core 有一個(gè)名為 IHostApplicationLifetime 的接口,允許您在應(yīng)用程序啟動(dòng)或關(guān)閉時(shí)運(yùn)行自定義代碼。您可以利用此接口的 Register 方法來(lái)注冊(cè)事件。
Startup 類(lèi)的 Configure 方法可以接受以下參數(shù):
- IApplicationBuilder
- IHostingEnvironment
- ILoggerFactory
- IHostApplicationLifetime
以下代碼演示了如何使用 IHostApplicationLifetime 接口注冊(cè)對(duì)象以在應(yīng)用程序關(guān)閉時(shí)進(jìn)行處置。??
??
public void Configure(IApplicationBuilder app, IHostApplicationLifetime hostApplicationLifetime) {
hostApplicationLifetime.ApplicationStopping.Register(OnShutdown);
}
private void OnShutdown() {
// 釋放對(duì)象的代碼
}
?
最后,ASP.NET Core 6 中默認(rèn)不會(huì)創(chuàng)建 Startup.cs。我們需要手動(dòng)創(chuàng)建一個(gè),然后在 Program.cs 文件中編寫(xiě)以下代碼以指定您將在其中使用的 Startup 類(lèi)應(yīng)用程序。??
??
var builder = WebApplication.CreateBuilder(args);
builder.Host.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
});
using var app = builder.Build();
app.Run();
與 Finalize 不同,我們顯式使用 Dispose 方法來(lái)釋放非托管資源。您應(yīng)該在實(shí)現(xiàn)它的任何對(duì)象上顯式調(diào)用 Dispose 方法,以釋放該對(duì)象可能持有其引用的任何非托管資源。
?
參考資料:
1.???C#教程??
2.???編程寶庫(kù)??