DispatchQueue یک صف بنیادین چارچوب Grand Central Dispatch (GCD) برای مدیریت وظایف ناهمگام در iOS و macOS است. به گفته Apple Developer Documentation, 2026، DispatchQueue مدیریت نخها را از طریق صفهای serial و concurrent از توسعهدهنده انتزاع میکند. GCD به طور خودکار وظایف را در سراسر استخر نخهای سیستم توزیع میکند و نیاز به ایجاد و نابودی دستی نخها را از بین میبرد.
نکات اصلی
DispatchQueue یک شی از چارچوب Grand Central Dispatch (GCD) است که اجرای وظایف را در صفهای نخ سیستمی یا سفارشی مدیریت میکند. Grand Central Dispatch یک کتابخانه سطح پایین اپل است که از iOS 4 و macOS 10.6 در دسترس است و مدیریت نخها را کاملاً از توسعهدهنده انتزاع میکند. GCD از استخر نخهای سیستم عامل استفاده میکند و به طور خودکار تعداد نخها را بر اساس بار دستگاه مقیاسپذیر میکند.
توسعهدهنده نیازی به ایجاد و نابودی دستی نخها ندارد — GCD این وظیفه را بر عهده میگیرد و یک API ساده از طریق DispatchQueue ارائه میدهد. وظیفه به صورت closure (بستار) از طریق متدهای sync یا async به صف ارسال میشود. در حالت اول، نخ فراخوان تا پایان وظیفه مسدود میشود، در حالت دوم بلافاصله به اجرا ادامه میدهد.
به گفته اپل (2026)، GCD از استخر نخ سیستم استفاده میکند که با تعداد هستهها و بار فعلی پردازنده سازگار میشود. صف concurrent برای هر وظیفه یک نخ جدید ایجاد نمیکند — GCD نخها را از استخر مجدداً استفاده میکند که هزینههای سربار ایجاد نخ را به حداقل میرساند.
Grand Central Dispatch از سه مؤلفه کلیدی تشکیل شده است: صف (DispatchQueue)، گروه (DispatchGroup) و سمافور (DispatchSemaphore). صف عنصر اصلی است که وظایف را به صورت بلوکهای کد دریافت میکند. DispatchGroup اجرای چندین وظیفه را همگامسازی میکند و DispatchSemaphore دسترسی به یک منبع مشترک را به تعداد مشخصی از نخها محدود میکند.
هر صف GCD با یک کلاس QoS (Quality of Service) خاص مرتبط است که به سیستم در مورد اهمیت وظیفه اطلاع میدهد. سیستم از QoS برای توزیع زمان پردازنده بین صفها استفاده میکند و به وظایف بحرانیتر — مانند بهروزرسانی UI یا پردازش لمس کاربر — اولویت میدهد.
صف Serial وظایف را به صورت کاملاً متوالی، یکی پس از دیگری اجرا میکند. اگر سه وظیفه در صف serial قرار داده شود، دومی فقط پس از اتمام کامل اولی شروع میشود. صفهای serial برای همگامسازی دسترسی به منابع مشترک استفاده میشوند — مثلاً آرایهای که از چند بخش کد تغییر میکند.
صف Concurrent چندین وظیفه را همزمان اجرا میکند و آنها را بین نخهای موجود از استخر سیستم توزیع میکند. وظایف در صف concurrent به ترتیب ورود (FIFO) شروع میشوند، اما اگر زمان اجرای آنها متفاوت باشد، به ترتیب دلخواه به پایان میرسند. صف Concurrent ترتیب پایان را تضمین نمیکند — فقط ترتیب شروع را تضمین میکند.
| پارامتر | صف Serial | صف Concurrent |
|---|---|---|
| ترتیب اجرا | کاملاً متوالی | موازی |
| تعداد نخها | یک | چندین از استخر GCD |
| کاربرد | حفاظت از منابع مشترک | محاسبات مستقل |
| Main queue | بله (نخ اصلی) | خیر |
| ریسک Deadlock | بالا در sync روی همان صف | کم |
صف serial برای وظایفی که وضعیت مشترک را تغییر میدهند ایدهآل است — نوشتن در فایل، بهروزرسانی مدل داده یا کار با Core Data. استفاده از صف serial تضمین میکند که دو بخش کد همزمان دادههای یکسانی را تغییر نمیدهند و شرایط رقابت را بدون قفلهای اضافی حذف میکند.
صف Concurrent برای وظایفی که به یکدیگر وابسته نیستند مناسب است: بارگذاری چندین تصویر، درخواستهای شبکه موازی یا پردازش دستهای دادهها. GCD به طور خودکار تصمیم میگیرد که چند وظیفه همزمان بر اساس تعداد هستههای پردازنده و بار فعلی سیستم اجرا شود.
QoS (Quality of Service) — مکانیزم GCD که به سیستم عامل در مورد اهمیت و فوریت وظیفه اطلاع میدهد. سیستم از QoS برای برنامهریزی نخها استفاده میکند: وظایف با QoS بالاتر زمان پردازنده بیشتری دریافت میکنند و زودتر اجرا میشوند. مقدار QoS هنگام ایجاد صف یا ارسال وظیفه خاص منتقل میشود.
در GCD پنج کلاس QoS موجود است. .userInteractive — بالاترین اولویت برای وظایف مرتبط با UI. .userInitiated — برای وظایف آغاز شده توسط کاربر. .utility — برای وظایف پسزمینه با نمایش پیشرفت. .background — برای وظایف نامرئی برای کاربر. .default — سطح میانی بین userInitiated و utility، به طور پیشفرض استفاده میشود.
به گفته اپل (2026)، انتخاب نادرست QoS یکی از دلایل رایج مشکلات عملکرد است. اجرای بارگیری پسزمینه با QoS .userInteractive منابع را از UI میگیرد و باعث میکرو لگ در انیمیشنها میشود. توصیه میشود پایینترین QoS را انتخاب کنید که همچنان زمان اجرای قابل قبولی را فراهم میکند.
هنگام بارگیری تصویر برای نمایش فوری از .userInitiated استفاده کنید — کاربر انتظار نتیجه را دارد. برای پیشبارگیری صفحه بعد، .utility کافی است. همگامسازی پسزمینه با سرور با .background اجرا میشود و تأثیر بر وظایف فعال را به حداقل میرساند.
DispatchGroup امکان ردیابی اتمام یک گروه از وظایف را فراهم میکند. وقتی همه وظایف در گروه کامل شدند، GCD هندلر notify را در صف مشخص شده فراخوانی میکند. این به ویژه هنگام بارگیری چندین منبع مستقل — دادههای پروفایل، لیست دوستان و تنظیمات — مفید است، زمانی که رابط باید فقط پس از دریافت همه دادهها بهروزرسانی شود.
DispatchGroup از فراخوان همگام wait() پشتیبانی میکند که نخ فعلی را تا اتمام همه وظایف مسدود میکند. این زمانی راحت است که کد نمیتواند بدون نتایج گروه ادامه یابد. نسخه ناهمگام — notify() — پس از اتمام همه وظایف، closure را در صف مشخص شده فراخوانی میکند بدون اینکه نخ فراخوان را مسدود کند.
DispatchSemaphore دسترسی به یک منبع را کنترل میکند و تعداد دسترسیهای همزمان را محدود میکند. سمافور با مقدار اولیه 3 اجازه اجرای حداکثر سه وظیفه موازی را میدهد. هنگام فراخوانی wait() شمارنده کاهش مییابد، هنگام signal() افزایش مییابد. اگر شمارنده صفر باشد، نخ تا آزاد شدن منبع مسدود میشود.
سه مثال عملی استفاده از DispatchQueue در Swift را بررسی میکنیم. اولین مورد فراخوان پایه async با بازگشت به نخ اصلی را نشان میدهد، دومین — همگامسازی از طریق صف serial، سومین — DispatchGroup برای درخواستهای موازی.
DispatchQueue.main — صف serial نخ اصلی است که منحصراً برای عملیات UI در نظر گرفته شده است. همیشه از آن برای بهروزرسانی رابط پس از اتمام کار پسزمینه استفاده کنید.
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
let data = self.fetchData()
DispatchQueue.main.async {
self.updateUI(with: data)
}
}
ایجاد صف serial خود با شناسه منحصربهفرد، دسترسی به آرایه قابل تغییر را همگامسازی میکند. تمام عملیات خواندن و نوشتن از یک صف عبور میکنند و شرایط رقابت را حذف میکنند.
let serialQueue = DispatchQueue(label: "com.app.items")
var items: [Int] = []
serialQueue.async {
items.append(1)
}
serialQueue.async {
let last = items.last
DispatchQueue.main.async {
print("Last item: \(last)")
}
}
DispatchGroup امکان اجرای چندین وظیفه در صف concurrent و دریافت اعلان اتمام همه آنها را فراهم میکند. این برای بارگیری دادههای صفحه پروفایل مفید است.
let group = DispatchGroup()
let worker = DispatchQueue.global()
worker.async(group: group) { self.loadProfile() }
worker.async(group: group) { self.loadFriends() }
worker.async(group: group) { self.loadSettings() }
group.notify(queue: DispatchQueue.main) {
self.showCompleteUI()
}
Deadlock هنگام فراخوان sync در صف serial — رایجترین خطا. اگر وظیفهای در صف serial queue.sync را روی همان صف فراخوانی کند، نخ برای همیشه مسدود میشود. صف منتظر اتمام وظیفه فعلی است و وظیفه منتظر اتمام فراخوان sync — یک بنبست کلاسیک متقابل.
تمام عملیات با UIKit باید در نخ اصلی انجام شود. Xcode این خطاها را در حالت Debug از طریق Main Thread Checker شناسایی میکند. در نسخه Release، آنها منجر به رفتار غیرقابل پیشبینی میشوند: انیمیشنها اجرا نمیشوند، UI بهروزرسانی نمیشود، کرش ممکن است.
ایجاد صدها صف سفارشی به جای صفهای جهانی — ضدالگو. هر صف منابع سیستم را مصرف میکند. برای بیشتر وظایف، صفهای concurrent جهانی با QoS مختلف و یکی دو صف serial برای همگامسازی دادههای مشترک کافی است.
هنگام اجرای وظایف چرخهای منابعنگار در صف پسزمینه بدون autoreleasepool، حافظه تا پایان کل حلقه رشد میکند. ARC اشیاء را فقط هنگام خروج از autorelease pool آزاد میکند. تکرارهای حلقه را برای آزادسازی بهموقع حافظه در autoreleasepool { } قرار دهید.
سوالات متداول
OperationQueue بر روی GCD ساخته شده است اما API سطح بالاتری با وابستگیهای عملیات، KVO و پشتیبانی از لغو ارائه میدهد. DispatchQueue یک صف سطح پایین برای وظایف ساده async بدون مدیریت وابستگی است.
GCD از توقف وظیفه در حال اجرا پشتیبانی نمیکند. متد suspend() فقط وظایف جدید را متوقف میکند، وظیفه فعلی تا پایان اجرا میشود. برای لغو، بررسی دستی پرچم در داخل کد وظیفه لازم است.
برای درخواست اصلی با نمایش فوری نتیجه — .userInitiated. برای پیشبارگیری دادهها — .utility. برای همگامسازی پسزمینه — .background.
GCD تعداد نخها را ثابت نمیکند. استخر نخها به صورت پویا تحت بار مقیاسپذیر میشود و هستههای پردازنده، بار فعلی و QoS هر وظیفه را در نظر میگیرد. حداکثر تعداد توسط سیستم محدود میشود.
UIKit thread-safe نیست — تمام کلاسهای آن باید فقط از نخ اصلی فراخوانی شوند. نقض باعث رفتار غیرقابل پیشبینی، بهروزرسانیهای از دست رفته و کرش در Production میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید