1024programmer Asp.Net Clear ExecutionContext to prevent AsyncLocal from being passed in asynchronous streams and Threads

Clear ExecutionContext to prevent AsyncLocal from being passed in asynchronous streams and Threads

Clear the ExecutionContext and prevent AsyncLocal from being passed in asynchronous streams and Thread

Foreword:

Since using AsyncLocal, I have found that AsyncLocal variables are like a bug. Tasks or Threads started in a thread with AsyncLocal variables will come with AsyncLocal variables .

In the project, AsyncLocal is used to implement global and local work units, but it is impossible to open multiple threads in subsequent jobs (the requirement is to open multiple threads, and I have no choice ), subsequent started multi-threads will have AsyncLocal variables, directly leading to Report errors, such as DBContext is not thread-safe…

In fact, I have always believed that it is inappropriate to open multiple threads in one HTTP request. The tasks that need to be performed should be given to “Background Worker Thread” or to “Background Job” ”, but the situation in the real world is very complicated, what should we do? What else can we do to open multiple threads in Http requests? Let’s solve the problem of ExecutionContext and AsyncLocal passing.

 ”People learn something every day, and what they often learn is that what they learned yesterday is wrong.

ExecutionContext in Thread

Create a thread and start it. The delegate executed by Thread will get the value set outside the thread by “AsyncLocalTest.Lang.Value” .

 

Why does Thread get the value in the external AsyncLocal variable? Take a deep look at the source code, as shown below.

 

Good guys, when Thread.Start() originally started the thread, it executed ExecutionContext.Capture() to obtain the thread execution context, that is, ExecutionContext

 As shown below, you can see that the ExecutionContext can be obtained in the Thread thread. From the ExecutionContext, you can see the AsyncLocal variable stored above

 

ExecutionContext in Task

When declaring a Task, dig into the source code to view

 

Task will execute an internal constructor

 

In the Task constructor, it turns out that ExecutionContext

is obtained by executing ExecutionContext.Capture()

 

When creating a Task, the Task automatically obtains the “Thread execution context, ExecutionContext“.

PreventExecutionContext from flowing

 How to prevent the flow of ExecutionContext, please check this article https://www.cnblogs.com/eventhorizon/p/12240767.html#3executioncontext-%E7%9A%84%E6%B5 %81%E5%8A%A8, so I won’t go into details.

Implement a partially clean ExecutionContext

 1. Implement a DisposeAction. I don’t know how to call it. Please look at the code. The source code comes only from the ABP framework, I copied it directly strong>. The principle is that when the Using code block is released, this “Action delegate” is executed.

 /// 
     /// Source code comes from ABP Vnext  frame
     /// 
     public class DisposeAction : IDisposable{
         private readonly  span> Action _action;

         public DisposeAction([  NotNull] Action action)
         {
             _action = action ?? throw new ArgumentNullException(nameof(action));
         }

         public void  span> Dispose()
         {
             _action();
         }
     }

DisposeAction

 2. As we all know, ExecutionContext.SuppressFlow() blocks the flow of ExecutionContext. ExecutionContext.RestoreFlow(), starts the ExecutionContext flow.

3. Implement partial blocking of ExecutionContext flowing core code

 public class SuppressExecutionContextFlow
     {
         public static  span> IDisposable CleanEnvironment()
         {
             // Block  ExecutionContext flow
  ExecutionContext.SuppressFlow();
             return new  span> DisposeAction(() =>
             {
                 if (ExecutionContext.  IsFlowSuppressed())
                 {
                     ExecutionContext.RestoreFlow();
                 }
             });
         }
     }

SuppressExecutionContextFlow.CleanEnvironment

4. Test the code and debug it as you like

//6. Create  A clean ExecutionContext environment for use
 var scheduler = new  QueuedTaskScheduler(2);
 AsyncLocalTest.Lang.Value = "test";
 using (SuppressExecutionContextFlow.  CleanEnvironment())
 {
     Task task11 = new Task(() =>
     {
         var aa = ExecutionContext  .Capture();
         Console.WriteLine("task11 thread:" + AsyncLocalTest.Lang.Value);
     });
     Thread th = new Thread(() =>
     {
         var aa = ExecutionContext  .Capture();
         Console.WriteLine("th thread:" + AsyncLocalTest.Lang.Value);
     });
     th.Start();
     task11.Start(scheduler);
 }
 Console.WriteLine("Main thread:" + AsyncLocalTest.Lang.Value);
 Console.Read();

Clean ExecutionContext environment

Debugging.gif

 

Since then implementing a partially clean ExecutionContext is completed, my code reference https://github.com/qiqiqiyaya/Learning-Case/tree/main/CleanExecutionContext

The author of this article: youliCC

Please indicate the original link when reprinting: https://www.cnblogs.com/youlicc/p/17410530.html

e);
Console.Read();

Clean ExecutionContext environment

Debugging.gif

 

Since then implementing a partially clean ExecutionContext is completed, my code reference https://github.com/qiqiqiyaya/Learning-Case/tree/main/CleanExecutionContext

The author of this article: youliCC

Please indicate the original link when reprinting: https://www.cnblogs.com/youlicc/p/17410530.html

This article is from the internet and does not represent1024programmerPosition, please indicate the source when reprinting:https://www.1024programmer.com/clear-executioncontext-to-prevent-asynclocal-from-being-passed-in-asynchronous-streams-and-threads/

author: admin

Previous article
Next article

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

Contact us

181-3619-1160

Online consultation: QQ交谈

E-mail: [email protected]

Working hours: Monday to Friday, 9:00-17:30, holidays off

Follow wechat
Scan wechat and follow us

Scan wechat and follow us

Follow Weibo
Back to top
首页
微信
电话
搜索