AsnycLocal與ThreadLocal

AsnycLocal與ThreadLocal

AsnyncLocal與ThreadLocal都是存儲線程上下文的變量,可是,在實際使用過程當中二者又有區別主要的表如今:json

  • AsyncLocal變量能夠在父子線程中傳遞,建立子線程時父線程會將本身的AsyncLocal類型的上下文變量賦值到子線程中,可是,當子線程改變線程上下文中AsnycLocal變量值後,父線程不會同步改變。也就是說AsnycLocal變量只會影響他的子線程,不會影響他的父級線程。
  • TreadLocal只是當前線程的上下文變量,不能在父子線程間同步。
using System;
using System.Threading;
using System.Threading.Tasks;

namespace await_aysnc
{
    class Program
    {
        static ThreadLocal<int> ThreadObj = new ThreadLocal<int>();
        static AsyncLocal<int> AsyncObj = new AsyncLocal<int>();

        static void Main(string[] args)
        {
            AsyncObj.Value = 1;
            ThreadObj.Value = 1;
            Console.WriteLine($"Task執行前:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
            Task.Run(async() =>
            {
                Console.WriteLine($"RunAsync異步執行前:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
                await RunAsync();
                Console.WriteLine($"RunAsync異步執行後:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
            });
            Console.WriteLine($"Task執行後:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
            Console.Read();
        }

        static async Task RunAsync()
        {           
            Console.WriteLine($"Delay異步執行前:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId} ");
            AsyncObj.Value = 2;
            ThreadObj.Value = 2;
            await Task.Delay(100);
            Console.WriteLine($"Delay異步執行後:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
        }
    }

}
Task執行前:AsyncObj= 1 ThreadObj= 1 ThreeadId = 1
Task執行後:AsyncObj= 1 ThreadObj= 1 ThreeadId = 1
RunAsync異步執行前:AsyncObj= 1 ThreadObj= 0 ThreeadId = 3
Delay異步執行前:AsyncObj = 1 ThreadObj= 0 ThreeadId = 3
Delay異步執行後:AsyncObj = 2 ThreadObj= 0 ThreeadId = 4
RunAsync異步執行後:AsyncObj = 1 ThreadObj= 0 ThreeadId = 4

從結果上能夠看出一下結論:c#

  • RunAsync執行前ThreadLocal值被切成0即ThreadLocal變量在新線程裏面沒有繼承主線程的上下文變量,可是AsyncLocal繼承了。
  • Delay返回後,線程id變了,同時,TheadLocal中的變量爲0。
  • RunAsync結束後AyncLocal又切回主線程的上下文值,,一樣Threadlocal中的值丟失。
  • 因爲await執行完返回以後,.net會在線程池中隨機選取一個線程來執行await以後的邏輯,因此,await以後同時也會有必定概率獲取到以前的線程,若是出現這種情形,TreadLocal會獲取到以前的上下文,此時會出現意料以外的問題,從現象上看報錯可能會是一個機率性問題。
相關文章
相關標籤/搜索