共用方式為


Azure SDK 物件的線程安全性和用戶端存留期管理

本文可協助您瞭解使用 Azure SDK 時的線程安全性問題。 它也會討論 SDK 的設計如何影響用戶端存留期管理。 您將了解為何不需要處置 Azure SDK 客戶端物件。

執行緒安全

所有 Azure SDK 用戶端物件都是安全線程且彼此獨立。 此設計可確保重複使用用戶端實例一律安全,即使在線程之間也一樣。 例如,下列程式代碼會啟動多個工作,但為安全線程:

var client = new SecretClient(
    new Uri("<secrets_endpoint>"), new DefaultAzureCredential());

foreach (var secretName in secretNames)
{
    // Using clients from parallel threads
    Task.Run(() => Console.WriteLine(client.GetSecret(secretName).Value));
}

SDK 用戶端所使用的模型對象,無論是輸入或輸出模型,預設不是安全線程。 大部分涉及模型物件的使用案例只會使用單一線程。 因此,將這些物件實作同步處理作為默認行為的成本太高。 下列程式代碼說明從多個線程存取模型的 Bug,可能會導致未定義的行為:

KeyVaultSecret newSecret = client.SetSecret("secret", "value");

foreach (var tag in tags)
{
    // Don't use model type from parallel threads
    Task.Run(() => newSecret.Properties.Tags[tag] = CalculateTagValue(tag));
}

client.UpdateSecretProperties(newSecret.Properties);

若要從不同的線程存取模型,您必須實作自己的同步處理程序代碼。 例如:

KeyVaultSecret newSecret = client.SetSecret("secret", "value");

// Code omitted for brevity

foreach (var tag in tags)
{
    Task.Run(() =>
    {
        lock (newSecret)
        {
            newSecret.Properties.Tags[tag] = CalculateTagValue(tag);
        }
    );
}

client.UpdateSecretProperties(newSecret.Properties);

用戶端存留期

因為 Azure SDK 用戶端是安全線程,因此沒有理由針對一組指定的建構函式參數建構多個 SDK 用戶端物件。 建構后,將 Azure SDK 用戶端物件視為單一物件。 此建議通常是藉由將 Azure SDK 用戶端物件註冊為應用程式控制反向容器中的單一對象來實作。 相依性插入 (DI) 可用來取得 SDK 用戶端對象的參考。 下列範例顯示單一客戶端物件註冊:

var builder = Host.CreateApplicationBuilder(args);

var endpoint = builder.Configuration["SecretsEndpoint"];
var blobServiceClient = new BlobServiceClient(
    new Uri(endpoint), new DefaultAzureCredential());

builder.Services.AddSingleton(blobServiceClient);

如需使用 Azure SDK 實作 DI 的詳細資訊,請參閱 Azure SDK for .NET 的相依性插入

或者,您可以建立 SDK 用戶端實例,並將它提供給需要用戶端的方法。 重點是避免使用相同參數對相同 SDK 用戶端物件的不必要的具現化。 既不必要又浪費。

用戶端無法處置

經常出現兩個最終問題如下:

  • 當我完成使用這些物件時,是否需要處置 Azure SDK 用戶端物件?
  • 為什麼 HTTP 型 Azure SDK 用戶端物件無法處置?

在內部,所有 Azure SDK 用戶端都會使用單一共享 HttpClient 實例。 用戶端不會建立任何其他需要主動釋放的資源。 共用 HttpClient 實例會在整個應用程式存留期內保存。

// Both clients reuse the shared HttpClient and don't need to be disposed
var blobClient = new BlobClient(new Uri(sasUri));
var blobClient2 = new BlobClient(new Uri(sasUri2));

可以將的 HttpClient 自定義實例提供給 Azure SDK 客戶端物件。 在此情況下,您必須負責管理 HttpClient 存留期,並在正確的時間正確處置該存留期。

var httpClient = new HttpClient();

var clientOptions = new BlobClientOptions()
{
    Transport = new HttpClientTransport(httpClient)
};

// Both clients would use the HttpClient instance provided in clientOptions
var blobClient = new BlobClient(new Uri(sasUri), clientOptions);
var blobClient2 = new BlobClient(new Uri(sasUri2), clientOptions);

// Code omitted for brevity

// You're responsible for properly disposing httpClient some time later
httpClient.Dispose();

如需正確管理和處置實例的 HttpClient 進一步指引,請參閱 HttpClient 檔。

另請參閱