TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 549 subscribers
Post #797 256
⏱️ ءPeriodicTimer در NET.؛ چه زمانی بهتر از Task.Delay است؟

خیلی وقت‌ها در پروژه‌های NET. نیاز داریم یک عملیات را به‌صورت دوره‌ای اجرا کنیم:
🔹 هر ۳۰ ثانیه وضعیت سفارش‌ها را بررسی کنیم
🔹 هر ۵ دقیقه Cache را Refresh کنیم
🔹 هر یک دقیقه Jobهای Pending را پردازش کنیم
🔹 هر چند دقیقه اطلاعات یک سرویس خارجی را Sync کنیم
اولین چیزی که خیلی از Developerها می‌نویسند چیزی شبیه این است:
while (!cancellationToken.IsCancellationRequested)
{
await DoSomethingAsync();

await Task.Delay(
TimeSpan.FromMinutes(5),
cancellationToken);
}

این کد کاملاً معتبر است و در بسیاری از سناریوها هم انتخاب خوبی است.
اما از NET 6. به بعد، یک API مشخص برای همین مدل سناریو داریم: PeriodicTimer
مایکروسافت آن را به‌عنوان Timerای معرفی می‌کند که امکان waiting asynchronously for timer ticks را فراهم می‌کند.

⏱️ ءPeriodicTimer دقیقاً چیست؟
ءPeriodicTimer در namespace زیر قرار دارد:
System.Threading

و استفاده اصلی آن این است که به‌جای Callback-based Timer، منتظر Tick بعدی Timer بمانیم:
using var timer = new PeriodicTimer(
TimeSpan.FromMinutes(5));

while (await timer.WaitForNextTickAsync(cancellationToken))
{
await DoSomethingAsync(cancellationToken);
}

اینجا یک نکته مهم وجود دارد:
ء( )WaitForNextTickAsync یک <ValueTask<bool برمی‌گرداند.
تا زمانی که Tick بعدی اتفاق نیفتاده، کد شما منتظر می‌ماند و بعد از Tick وارد بدنه حلقه می‌شود.
اگر Timer متوقف شود، این متد می‌تواند false برگرداند و حلقه تمام شود. همچنین ( )Dispose می‌تواند یک WaitForNextTickAsync فعال را متوقف کند و باعث شود false برگردد.
🔄 پس چه فرقی با Task.Delay دارد؟
مثلاً این دو کد را ببینید.
با Task.Delay:
while (!cancellationToken.IsCancellationRequested)
{
await DoSomethingAsync(cancellationToken);

await Task.Delay(
TimeSpan.FromMinutes(5),
cancellationToken);
}

و با PeriodicTimer:
using var timer = new PeriodicTimer(
TimeSpan.FromMinutes(5));

while (await timer.WaitForNextTickAsync(
cancellationToken))
{
await DoSomethingAsync(cancellationToken);
}

از نظر نتیجه ظاهری، هر دو می‌توانند یک کار را به‌صورت دوره‌ای اجرا کنند.
اما مدل ذهنی آن‌ها متفاوت است.
ءTask.Delay می‌گوید:
بعد از این مدت دوباره ادامه بده.

در حالی که PeriodicTimer می‌گوید:
من یک Timer دوره‌ای دارم؛ وقتی Tick بعدی رسید، اجازه بده ادامه بدهم.

برای سناریوهایی که ذاتاً periodic هستند، این مدل بسیار واضح‌تر است.
⚠️ اما یک اشتباه مهم
نباید تصور کنیم:
PeriodicTimer

یعنی Job شما هر دقیقاً ۵ دقیقه یک‌بار اجرا می‌شود.
فرض کنید:
Period = 5 minutes

Tick #1
↓
DoSomethingAsync()
↓
7 minutes
↓
Tick #2

در این مدت شما دوباره WaitForNextTickAsync() را صدا نزده‌اید.
طبق مستندات، PeriodicTimer برای استفاده توسط یک consumer در هر لحظه طراحی شده است و فقط یک WaitForNextTickAsync() باید هم‌زمان در حال انتظار باشد.
بنابراین نباید از آن انتظار داشته باشید که برای هر Tick یک اجرای موازی از Job ایجاد کند.
🧠 این رفتار در BackgroundService خیلی کاربردی است
مثلاً فرض کنید در یک سیستم فروشگاهی می‌خواهیم هر ۳۰ ثانیه سفارش‌های Pending را بررسی کنیم:
public sealed class OrderWorker(
IServiceScopeFactory scopeFactory)
: BackgroundService
{
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
using var timer = new PeriodicTimer(
TimeSpan.FromSeconds(30));

while (await timer.WaitForNextTickAsync(
stoppingToken))
{
using var scope =
scopeFactory.CreateScope();

var service =
scope.ServiceProvider
.GetRequiredService<IOrderService>();

await service.ProcessPendingOrdersAsync(
stoppingToken);
}
}
}

اینجا Flow کاملاً مشخص است
و وقتی Application در حال Shutdown باشد، CancellationToken می‌تواند انتظار Timer را متوقف کند.
📌 پس PeriodicTimer برای چه چیزی مناسب است؟
✅ اجرای Periodic یک عملیات درون یک Process
✅ ءBackground Workerهای ساده
✅ ءPolling
✅ ءCache Refresh
✅ بررسی دوره‌ای وضعیت
✅ ءCleanupهای ساده
✅ ءSync دوره‌ای
و مخصوصاً زمانی که می‌خواهید این منطق را به‌شکل async و قابل Cancellation بنویسید.
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →