بایگانی برچسب: QueueBackgroundWorkItem

استفاده از QueueBackgroundWorkItem برای به تاخیر انداختن کارها در اپلیکیشن های asp.net 4.5.2

ارسال شده در: ASP.NET . کدنویسی

با انتشار نسخه‌ی ۴.۵.۲ از .Net حالا ASP.NET در فضای نام System.Web.Hosting از HostingEnvironment.QueueBackgroundWorkItem پشتیبانی می‌کند. در این نوشته سعی می‌کنم از آن در ASP.NET MVC استفاده کنم.

hosting_environment_queue_background_work_item

پیش از آن، می‌توانید از وبلاگ متخصصان مایکروسافت و یا MSDN دیگر امکاناتی که در .NET 4.5.2 قرار گرفته است را ببینید.

Announcing the .NET Framework 4.5.2 What’s New in the .NET Framework 4.5, 4.5.1, and 4.5.2

وظیفه‌ی QueueBackgroundWorkItem چیست؟

در توضیحات انتشار (release note) در مورد QueueBackgroundWorkItem آمده:

The HostingEnvironment.QueueBackgroundWorkItem method lets you schedule small background work items. ASP.NET tracks these items and prevents IIS from abruptly terminating the worker process until all background work items have completed.

این توضیح مخصوصا جایی که bold کردم، دلیل خوبی برای استفاده از QueueBackgroundWorkItem خواهد بود. دیگر نیازی نیست نگران متوقف شدن IIS هنگام کارهای پس‌زمینه باشیم!

لازم به ذکر است که QueueBackgroundWorkItem فقط در ASP.NET managed کار می‌کند. Using Application Domains را مطالعه کنید.

استفاده ساده از متد QueueBackgroundWorkItem

QueueBackgroundWorkItem دو تا overload داره. که هر کدام یک ورودی دارند. می‌توان هر کدام از delegateهای زیر را به آن پاس داد:

  • Action
  • Func

تکه کد زیر چگونگی صدا زدن اولین overload با استفاده از عبارت lambda را نشان می‌دهد:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
    // Some long-running job
});

عبارت lambda حتی می‌تواند از async استفاده کند. که با آن می‌توان از تمام مزایای await هم بهره برد:

HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken =>
{
    var result = await LongRunningMethodAsync();

    // Do something with result
    // ...
});

می‌توان یک متد را به وسیله‌ی عبارت Func به QueueBackgroundWorkItem ارسال کرد.

private void QueueWorkItem()
{
    Func<CancellationToken, Task> workItem = LongRunningMethodAsync;
    HostingEnvironment.QueueBackgroundWorkItem(workItem);
}

private async Task LongRunningMethodAsync(CancellationToken cancellationToken)
{
    // Some long-running job
}

از آنجایی که کامپایلرهای C# متدهایی که پاس می‌دهیم را تبدیل (conversion) می‌کنند نمی‌توان مستقیمن LongRunningMethodAsync را به QueueBackgroundWorkItem پاس داد. مشکل این‌جاست که وقتی متد را به QueueBackgroundWorkItem مستقیمن پاس بدهیم کامپایلر با استفاده از overload resolution آن را تبدیل می‌کند، که overload resolution کاری به مقدار بازگشتی متد ندارد. از آن‌جایی که هر دو overload در QueueBackgroundWorkItem یک پارامتر ورودی CancellationToken دارند، کامپایلر نمی‌داند باید کدام را صدا بزند و خطا رخ می‌دهد. برای درک بهتر به این پاسخ در StackOverflow نگاهی بیاندازید.

فراخوانی POST یک API در یک ASP.NET MVC Controller

(نوشتن پست‌های اینچنینی به فارسی کاری بسیار نا به هنجار است!)

در اینجا یک مثال کاملتر از اینکه QueueBackgroundWorkItem چگونه استفاده می‌شود می‌آورم. فرض کنیم که یک مدل به نام Foo ساخته‌ایم. و در controller می‌خواهیم یک API را که عملیات آن زمان‌بر است را صدا بزنیم.

public class FooController : Controller
{
    [HttpPost]
    public ActionResult Create(FooInputModel input)
    {
        // Process the input somehow
        // ...

        Action<CancellationToken> workItem = PostToRemoteService;
        HostingEnvironment.QueueBackgroundWorkItem(workItem);

        return View();
    }

    private async void PostToRemoteService(CancellationToken cancellationToken)
    {
        using (var client = new HttpClient())
        {
            var response = await client.PostAsync("http://example.com/endpoint",
                new StringContent("..."), cancellationToken);

            // Do something with response
            // ...
        }
   }

    // More action methods
    // ...
}

به این ترتیب، Action می‌تواند مقدار بازگشتی را پس از انجام عملیات روی ورودی ها (inputها) پس بفرستد (View) و نیازی نیست که منتظر تمام شدن صدا زدن API بماند.

پر واضح است که می‌توان از QueueBackgroundWorkItem در دیگر انواع پروژه ها و نه فقط ASP.NET MVC هم استفاده کرد.

خلاصه

همان‌طور که مشاهده کردید استفاده از QueueBackgroundWorkItem بسیار ساده‌ست. حالا دیگر ASP.NET می‌تواند از متوقف شدن IIS برای انجام کارهای به تاخیر افتاده و طولانی جلوگیری کند. به نظر می‌رسد که استفاده از QueueBackgroundWorkItem برای انجام scheduling کارهای کوچک بسیار مفید باشد.