Manajemen status asinkron

Paket 📦 Microsoft.Extensions.AsyncState NuGet menyediakan fungsionalitas untuk menyimpan dan mengambil objek dalam konteks asinkron saat ini. Paket ini menawarkan peningkatan performa dan kegunaan dibandingkan dengan menggunakan AsyncLocal<T> secara langsung, terutama ketika beberapa objek perlu dibagikan di antara operasi asinkron.

Mengapa menggunakan AsyncState

Meskipun .NET menyediakan AsyncLocal<T> untuk mengelola data sekitar dalam konteks asinkron, menggunakannya secara langsung dapat memiliki kelemahan:

  • Performa: Setiap AsyncLocal<T> instans menambahkan overhead. Ketika beberapa objek perlu mengalir melalui konteks asinkron, mengelola banyak AsyncLocal<T> instans dapat memengaruhi performa.
  • Abstraksi: Penggunaan AsyncLocal<T> secara langsung menghubungkan kode Anda ke implementasi tertentu, sehingga lebih sulit untuk dioptimalkan atau diubah di masa depan.
  • Manajemen seumur hidup: Paket AsyncState memberikan kontrol yang lebih baik atas masa pakai data sekitar melalui API eksplisit.

Paket Microsoft.Extensions.AsyncState membahas masalah ini dengan menyediakan:

  • Implementasi yang dioptimalkan yang mengurangi jumlah AsyncLocal<T> instans yang diperlukan.
  • Abstraksi yang jelas untuk menyimpan dan mengambil data lingkungan.
  • Integrasi dengan injeksi dependensi untuk pengujian dan konfigurasi yang lebih mudah.

Mulai

Untuk memulai dengan pengelolaan status asinkron, instal paket NuGet Microsoft.Extensions.AsyncState.

dotnet add package Microsoft.Extensions.AsyncState

Untuk informasi selengkapnya, lihat dotnet menambahkan paket atau Kelola dependensi paket dalam aplikasi .NET.

Mendaftarkan layanan status asinkron

Daftarkan layanan status asinkron ke dalam kontainer injeksi ketergantungan Anda menggunakan metode ekstensi AddAsyncState.

using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

services.AddAsyncState();

ServiceProvider provider = services.BuildServiceProvider();

Pendaftaran ini membuat antarmuka IAsyncContext<T> dan IAsyncState tersedia untuk penyuntikan dependensi.

Menggunakan IAsyncContext

Antarmuka IAsyncContext<T> menyediakan metode untuk mendapatkan dan mengatur nilai dalam konteks asinkron saat ini:

var context = provider.GetRequiredService<IAsyncContext<UserContext>>();

// Set a value in the async context
var userContext = new UserContext { UserId = "12345", UserName = "Alice" };
context.Set(userContext);

// Retrieve the value
if (context.TryGet(out var retrievedContext))
{
    Console.WriteLine($"User: {retrievedContext.UserName}");
}
public record class UserContext
{
    public required string UserId { get; set; }
    public required string UserName { get; set; }
}

Nilai yang ditetapkan dalam konteks mengalir melalui operasi asinkron, membuatnya tersedia untuk semua kode yang dijalankan dalam konteks asinkron yang sama.

Menggunakan IAsyncState

Antarmuka IAsyncState adalah antarmuka siklus hidup dasar yang IAsyncContext<T> diperluas. Ini menyediakan metode Initialize() dan Reset() untuk mengelola siklus hidup status asinkron. Untuk akses yang diketik ke nilai status asinkron, gunakan IAsyncContext<T>.

Contoh praktis: Meminta korelasi

Kasus penggunaan umum untuk status asinkron mempertahankan informasi korelasi di seluruh permintaan HTTP:

public class RequestProcessor(IAsyncContext<CorrelationContext> asyncContext)
{

    public async Task ProcessRequestAsync(string correlationId)
    {
        // Set correlation context at the beginning of request processing
        asyncContext.Set(new CorrelationContext { CorrelationId = correlationId });

        // The correlation ID flows through all async operations
        await Step1Async();
        await Step2Async();
    }

    private async Task Step1Async()
    {
        await Task.Yield();
        
        if (asyncContext.TryGet(out var context))
        {
            Console.WriteLine($"Step 1 - Correlation ID: {context.CorrelationId}");
        }
    }

    private async Task Step2Async()
    {
        await Task.Yield();
        
        if (asyncContext.TryGet(out var context))
        {
            Console.WriteLine($"Step 2 - Correlation ID: {context.CorrelationId}");
        }
    }
}
public class CorrelationContext
{
    public required string CorrelationId { get; set; }
}

Dalam contoh ini, ID korelasi diatur sekali di awal pemrosesan permintaan dan secara otomatis tersedia di semua operasi asinkron berikutnya tanpa perlu meneruskannya sebagai parameter.

integrasi ASP.NET Core

Dalam aplikasi ASP.NET Core, Anda dapat menggunakan status asinkron untuk mengalirkan informasi khusus permintaan melalui aplikasi Anda:

public class RequestHandler(IAsyncContext<RequestMetadata> asyncContext)
{

    public async Task<object> GetDataAsync()
    {
        await Task.Yield();
        
        if (asyncContext.TryGet(out var metadata))
        {
            var duration = DateTimeOffset.UtcNow - metadata.StartTime;
            return new
            {
                RequestId = metadata.RequestId,
                RequestPath = metadata.RequestPath,
                Duration = duration.TotalMilliseconds
            };
        }

        return new { Error = "No request metadata available" };
    }
}
public record class RequestMetadata
{
    public required string RequestId { get; set; }
    public required string RequestPath { get; set; }
    public DateTimeOffset StartTime { get; set; }
}

Praktik terbaik

Saat menggunakan status asinkron, pertimbangkan praktik terbaik berikut:

  • Batasi ukuran status: Jaga agar objek status asinkron tetap kecil untuk mengurangi overhead memori dan mempertahankan performa.
  • Menginisialisasi status lebih awal: Atur nilai status asinkron sedini mungkin untuk memastikan nilai tersebut tersedia untuk semua operasi asinkron hilir.
  • Status pembersihan: Atur ulang atau hapus status asinkron saat tidak lagi diperlukan untuk menghindari kebocoran memori dalam aplikasi yang berjalan lama.
  • Gunakan antarmuka yang sesuai: Gunakan IAsyncContext<T> untuk mendapatkan dan mengatur nilai yang ditik dalam konteks asinkron saat ini. Gunakan IAsyncState saat Anda perlu mengelola inisialisasi dan mengatur ulang siklus hidup secara langsung.
  • Type safety: Membuat jenis konteks tertentu daripada menggunakan kamus generik untuk menjaga keamanan jenis dan meningkatkan kejelasan kode.

Baca juga