در مطلب قبلی نحوه کار Thread Pool ارائه شد. در این مطلب به بررسی تفاوت بین متدهای async و sync میپردازیم که فرق بین این دو نوع چیست و چرا باید از متدهای async استفاده کنیم. زمانی که شما یک متد را به صورت sync مینویسید و به طور مثال میخواهید عملیات ذخیره کردن دیتاهارا انجام دهید, زمانی که به متد SaveChange میرسد, Thread جاری بلاک میشود و منتظر میماند تا کار متد SaveChange تمام شود سپس ادامه کار هارا انجام دهد. Thread هیچ تغییری نمیکند همان Thread قبلی است و با افزایش درخواست ها ممکن است به دلیل بلاک شدن Threadها باعث کندی سیستم شود و به همین صورت هم خواهد بود.

اما زمانی که همان متد را به صورت async بنویسید, زمانی که به متد SaveChange برسد, Thread جاری منتظر نمیماند که عملیات SaveChange به پایان برسد, بلکه به Thread pool برگردانده میشود و میتواند برای انجام Task دیگری مورد استفاده قرار گیرد و همین امر باعث افزایش پرفرمنس میشود. برای مثال کد زیر را در نظر بگیرید :

[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
    Console.WriteLine("Before DoSomething => " + Thread.CurrentThread.ManagedThreadId);
    var rng = new Random();
    DoSomething().GetAwaiter().GetResult();
    Console.WriteLine("After DoSomething => " + Thread.CurrentThread.ManagedThreadId);
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
}
private async Task DoSomething()
{
    await Task.Delay(5000);
}

زمانی که وارد متد Get میشوید ManagedThreadId جاری در صفحه کنسول نمایش داده خواهد شد. سپس وارد متد DoSomething میشود و یک مکث 5 ثانیه ای انجام میشود و سپس بقیه کار ها انجام میشود. چون که این متد به صورت sync نوشته شده است زمانی که به Task.Delay میرسد Thread جاری بلاک میشود و بعد از 5 ثانیه ادامه کار خود را انجام میدهد و اگر به صفحه کنسول نگاه کنید همه ی ManagedThreadId ها یکسان هستند. یعنی Thread تغییری نکرده است و در جای دیگری نمیتواند از آن استفاده شود. اگر پروژه را ران کنید و به اکشن Get یک ریکوئست ارسال کنید چنین خروجی مشاهده میکنید:

Before DoSomething => 10
After DoSomething => 10

ممکن است عدد نمایش داده شده در سیستم شما فرق کند ولی هردو ManagedThreadId ها یکسان هستند. اما اگر همین متد را به صورت async بنویسید, در بیشتر مواقع ManagedThreadId بعد از متد DoSomething فرق میکند. یعنی زمانی که به Task.Delay میرسد Thread جاری به Thread pool برگردانده میشود و مجددا بعد از 5 ثانیه یک Thread دیگری از Thread pool دریافت میکند و بقیه کارهارا انجام میدهد. اگر کد زیر را اجرا کنید:

[HttpGet("Async")]
public async Task<IEnumerable<WeatherForecast>> Async()
{
    Console.WriteLine("Before DoSomething async => " + Thread.CurrentThread.ManagedThreadId
    var rng = new Random();
    await DoSomething();
    Console.WriteLine("After DoSomething async => " + Thread.CurrentThread.ManagedThreadId)
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
}
private async Task DoSomething()
{
    await Task.Delay(5000);
}

چنین خروجی در کنسول دریافت میکنید:

Before DoSomething async => 11
After DoSomething async => 4

در واقع متدهایی که به صورت async نوشته شوند باعث افزایش کارایی سیستم خواهند شد.

;)

Powered by Froala Editor

نظرات