Use Tasks and Await

ב-interface שבנינו IProductsRepository אנחנו מחזירים List של Products.

public interface IProductsRepository
{
    public List<Product> GetAllProducts();
}

ה-List הזה כנראה יחזור מ-Dנ או משהו כזה, בכל מקרה זה יהיה מקום שהוא לא השרת שלי. בגלל זה יש פה משהו לא תקין שאנחנו מחזירים את האובייקט עצמו ולא Task.

הדרך הנכונה להחסיר את האובייקט היא על ידי Task:

public interface IProductsRepository
{
    public Task<List<Product>> GetAllProducts();
}

כאשר אנחנו פונים לשרת, והוא מבצע פנייה לשרת SQL לדוגמא, בשניות האלה ה-CPU שעובד הוא לא שלנו, הוא של המכונה שעובדת, למשל שרת ה-SQL. העיבוד קורה שם.

כל בקשה שמגיעה לשרת מקבלת Thread והוא פונה ל-SQL ובזמן שה-SQL מעבד את הנתונים הוא ממתין ומחכה לקבל תשובה בחזרה. כשאר אנחנו מדברים של 1,000 Threads שמסוגלים לעבוד במקביל ב-.NetCore יכול להיות ש-800 מחכים לתשובה מה-SQL. יש פה בזבוז משאבים. אנחנו ממתינים שמקום שה-thread ילך לעשות משהו אחר בינתיים.

מה מאפשר Task

כאשר אנחנו מחזירים Task יש לנו "צינור" שעוטף את המוצרים עצמם.

public class ProductsRepository : IProductsRepository
{
    public async Task<List<Product>> GetAllProducts() {
        await Task.Delay(1000);
        return new List<Product>() {
            new Product {
                id = 1,
                name = "ASUS Computer",
                description = "Best computer",
                price = 2400,
                amount = 4,
                producer = "Asus"
            }
        };
    }
}

כשנשתמש ב-Controller נצטרך לפנות עם async. ואז בזמן שאני ב-await ה-thread שמטפל בבקשה משתחרר ויכול ללכת לטפל בבקשות נוספות.

[HttpGet]
public async Task<ActionResult<List<Product>>> Get() {
    var result = await _productRepository.GetAllProducts();
    return Ok(result);
}

זאת הדרך לעבוד. אנחנו מגדירים את הפונקציות עם await כדי להשתמש נכון במשאבים.