Location>code7788 >text

The magic of AsyncLocal

Popularity:672 ℃/2025-01-13 16:07:52

AsyncLocal<T>It is a tool class used in .NET to maintain global variables in synchronous tasks and asynchronous tasks.

It allows you to retain a specific value in the same object in different threads, so that you can access this value in different functions and tasks.

This is an important means of maintaining consistency and elegance in implementing asynchronous tasks.

usage

Create an AsyncLocal instance:

you can useAsyncLocal<T>to create an instance of a specific type, such as:

AsyncLocal<string> asyncLocalString = new AsyncLocal<string>();

Setting value:

you can passValueProperty setting or reading value:

 = "Hello, AsyncLocal!";

Read value:

You can read this value anywhere in the task:

();

Instance sharing and value changes:

In different tasks and serial tasks,AsyncLocalThe values ​​of the instances are different:

= "Main Task";
 (() =>
 {
      = "Child Task";
     (); // Output "Child Task"
 });
 (); // Output "Main Task"

scene

Data transfer:

In asynchronous tasks, passAsyncLocalMake global data transfers without passing parameters. This is helpful for learning and reusing code.

Context management:

In Core,AsyncLocalCan be used to manage user request context and implement transfer between different requests. This is a very effective method when you need to save some request-related information.

Percentage information is saved:

Record specific information in different tasks and serial tasks, describing how these tasks are distributed. This is particularly useful when analyzing and tracing asynchronous operations.

System logs and traces:

AsyncLocalCan be used to save and share log and trace information in asynchronous tasks to collect the most useful information at runtime, which is helpful for problem tracking and analysis.

Example: Saving logs and tenant information

The following is a useAsyncLocalExample of saving logs and tenant information:

using System;
using ;
using ;

public class LogContext
{
    public string StackTrace { get; set; }
    public string UserInfo { get; set; }
}

public class TenantContext
{
    public string Name { get; set; }
}

public class Program
{
    private static AsyncLocal<LogContext> _logContext = new AsyncLocal<LogContext>();
    private static AsyncLocal<TenantContext> _tenantContext = new AsyncLocal<TenantContext>();

    public static async Task Main(string[] args)
    {
        _logContext.Value = new LogContext { StackTrace = "Main Stack Trace", UserInfo = "User1" };
        _tenantContext.Value = new TenantContext { Name = "Tenant A" };

        ($"Initial Log Context: {_logContext.}, User: {_logContext.}, Tenant: {_tenantContext.}");

        await (() => LogAndProcess(new LogContext { StackTrace = "Child Stack Trace", UserInfo = "User2" }, new TenantContext { Name = "Tenant B" }));

        ($"After Task Log Context: {_logContext.}, User: {_logContext.}, Tenant: {_tenantContext.}");
    }

    private static void LogAndProcess(LogContext logContext, TenantContext tenant)
    {
        _logContext.Value = logContext;
        _tenantContext.Value = tenant;

        ($"In Task Log Context: {_logContext.}, User: {_logContext.}, Tenant: {_tenantContext.}");

        // Simulate some processing
        (1000).Wait();

        ($"After Processing Log Context: {_logContext.}, User: {_logContext.}, Tenant: {_tenantContext.}");
    }
}

In this example,AsyncLocalUsed to save logs and tenant information to ensure that this information is correctly delivered and used in different task contexts.