DispatchQueue هي قائمة انتظار أساسية لـ Grand Central Dispatch (GCD) لإدارة المهام غير المتزامنة في iOS و macOS. وفقًا لـ Apple Developer Documentation, 2026، DispatchQueue تُجرّد إدارة الخيوط من المطور عبر قوائم انتظار تسلسلية ومتزامنة. يوزع GCD المهام تلقائيًا على مجموعة خيوط النظام، مما يلغي الحاجة إلى إنشاء الخيوط وتدميرها يدويًا.
الخلاصة
DispatchQueue هو كائن من إطار عمل Grand Central Dispatch (GCD) يدير تنفيذ المهام في قوائم انتظار خيوط النظام أو المخصصة. Grand Central Dispatch هي مكتبة منخفضة المستوى من Apple، متاحة منذ iOS 4 و macOS 10.6، تُجرّد إدارة الخيوط تمامًا من المطور. يستخدم GCD مجموعة خيوط نظام التشغيل ويوسع نطاق عدد الخيوط تلقائيًا وفقًا لحمل الجهاز.
لا يحتاج المطور إلى إنشاء الخيوط وتدميرها يدويًا — GCD يتولى هذه المهمة، مما يوفر API بسيط عبر DispatchQueue. تُرسل مهمة على شكل إغلاق (closure) إلى قائمة انتظار عبر طريقتي sync أو async. في الحالة الأولى، يُحظر الخيط المستدعي حتى اكتمال المهمة؛ في الحالة الثانية، يستمر التنفيذ فورًا.
وفقًا لـ Apple (2026)، يستخدم GCD مجموعة خيوط نظام تتكيف مع عدد النوى وحمل وحدة المعالجة المركزية الحالي. لا تنشئ قائمة الانتظار المتزامنة خيطًا جديدًا لكل مهمة — يعيد GCD استخدام الخيوط من المجموعة، مما يقلل من الحمل الإضافي لإنشاء الخيوط.
يتكون Grand Central Dispatch من ثلاثة مكونات رئيسية: قوائم الانتظار (DispatchQueue)، المجموعات (DispatchGroup)، والإشارات (DispatchSemaphore). قائمة الانتظار هي العنصر الأساسي الذي يقبل المهام على شكل كتل برمجية. تقوم DispatchGroup بمزامنة تنفيذ مهام متعددة، بينما يحد DispatchSemaphore الوصول إلى مورد مشترك بعدد معين من الخيوط.
ترتبط كل قائمة انتظار GCD بفئة QoS (جودة الخدمة) محددة، تُعلم النظام بأهمية المهمة. يستخدم النظام QoS لتوزيع وقت المعالجة بين قوائم الانتظار، مع إعطاء الأولوية للمهام الأكثر أهمية — مثل تحديث واجهة المستخدم أو معالجة لمسات المستخدم.
قائمة الانتظار التسلسلية تنفذ المهام بتسلسل صارم، واحدة تلو الأخرى. إذا تم وضع ثلاث مهام في قائمة انتظار تسلسلية، تبدأ الثانية فقط بعد اكتمال الأولى بالكامل. تُستخدم قوائم الانتظار التسلسلية لمزامنة الوصول إلى الموارد المشتركة — على سبيل المثال، مصفوفة يتم تعديلها من أجزاء متعددة من الكود.
قائمة الانتظار المتزامنة تشغل عدة مهام في وقت واحد، موزعة على الخيوط المتاحة من مجموعة النظام. تبدأ المهام في قائمة انتظار متزامنة بترتيب FIFO، ولكنها تكتمل بترتيب عشوائي إذا اختلفت أوقات تنفيذها. قائمة الانتظار المتزامنة لا تضمن ترتيب الاكتمال — فقط ترتيب البدء.
| المعامل | قائمة انتظار تسلسلية | قائمة انتظار متزامنة |
|---|---|---|
| ترتيب التنفيذ | تسلسلي صارم | متوازي |
| عدد الخيوط | واحد | متعدد من مجموعة GCD |
| الاستخدام | حماية الموارد المشتركة | حسابات مستقلة |
| قائمة الانتظار الرئيسية | نعم (الخيط الرئيسي) | لا |
| خطر الجمود | مرتفع عند استخدام sync على نفس القائمة | منخفض |
قائمة الانتظار التسلسلية مثالية للمهام التي تعدل حالة مشتركة — الكتابة إلى ملف، تحديث نموذج بيانات، أو العمل مع Core Data. يضمن استخدام قائمة انتظار تسلسلية أن جزأين من الكود لن يعدلا نفس البيانات في وقت واحد، مما يلغي حالات السباق دون أقفال إضافية.
قائمة الانتظار المتزامنة مناسبة للمهام التي لا تعتمد على بعضها البعض: تحميل عدة صور، طلبات شبكة متوازية، أو معالجة بيانات دفعة واحدة. يقرر GCD تلقائيًا عدد المهام التي يجب تشغيلها في وقت واحد بناءً على عدد نوى المعالج وحمل النظام الحالي.
QoS (جودة الخدمة) هي آلية GCD تُعلم نظام التشغيل بأهمية المهمة وإلحاحها. يستخدم النظام QoS لجدولة الخيوط: المهام ذات QoS الأعلى تحصل على وقت معالجة أكثر وتبدأ مبكرًا. تُمرر قيمة QoS عند إنشاء قائمة انتظار أو إرسال مهمة محددة.
يتوفر في GCD خمس فئات QoS. .userInteractive — أعلى أولوية للمهام المتعلقة بواجهة المستخدم. .userInitiated — للمهام التي بدأها المستخدم. .utility — للمهام الخلفية التي تظهر تقدمًا. .background — للمهام غير المرئية للمستخدم. .default — مستوى متوسط بين userInitiated و utility، يُستخدم افتراضيًا.
وفقًا لـ Apple (2026)، يُعد اختيار QoS غير الصحيح أحد الأسباب الشائعة لمشكلات الأداء. تشغيل تنزيل خلفي مع QoS .userInteractive يستهلك موارد واجهة المستخدم، مما يسبب تأخيرات دقيقة في الرسوم المتحركة. يُوصى باختيار أقل QoS لا يزال يوفر وقت تنفيذ مقبول.
عند تحميل صورة للعرض الفوري، استخدم .userInitiated — المستخدم يتوقع النتيجة. للتحميل المسبق للشاشة التالية، .utility كافٍ. تتم مزامنة الخلفية مع الخادم باستخدام .background، مما يقلل التأثير على المهام النشطة.
DispatchGroup يسمح بتتبع اكتمال مجموعة من المهام. عندما تكتمل جميع المهام في المجموعة، يستدعي GCD معالج notify في قائمة الانتظار المحددة. هذا مفيد بشكل خاص عند تحميل موارد مستقلة متعددة — بيانات الملف الشخصي، قائمة الأصدقاء، والإعدادات — حيث يجب تحديث الواجهة فقط بعد استلام جميع البيانات.
يدعم DispatchGroup استدعاءًا متزامنًا wait()، يحظر الخيط الحالي حتى اكتمال جميع المهام. هذا مناسب عندما لا يمكن للكود الاستمرار بدون نتائج المجموعة. البديل غير المتزامن notify() يستدعي إغلاقًا في قائمة الانتظار المحددة بعد اكتمال جميع المهام، دون حظر الخيط المستدعي.
DispatchSemaphore يتحكم في الوصول إلى مورد عن طريق تحديد عدد الوصول المتزامن. سيمافور بقيمة ابتدائية 3 يسمح بتشغيل ما لا يزيد عن ثلاث مهام متوازية. استدعاء wait() يقلل العداد، signal() يزيده. إذا وصل العداد إلى الصفر، يُحظر الخيط حتى يتوفر مورد.
لنلقِ نظرة على ثلاثة أمثلة عملية لاستخدام DispatchQueue في Swift. الأول يوضح استدعاء async أساسي مع العودة إلى الخيط الرئيسي، والثاني يظهر المزامنة عبر قائمة انتظار تسلسلية، والثالث يستخدم DispatchGroup للطلبات المتوازية.
DispatchQueue.main هي قائمة الانتظار التسلسلية للخيط الرئيسي، المخصصة حصريًا لعمليات واجهة المستخدم. استخدمها دائمًا لتحديث الواجهة بعد اكتمال العمل في الخلفية.
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
let data = self.fetchData()
DispatchQueue.main.async {
self.updateUI(with: data)
}
}
إنشاء قائمة انتظار تسلسلية مخصصة بمعرف فريد يزامن الوصول إلى مصفوفة قابلة للتغيير. تمر جميع عمليات القراءة والكتابة عبر قائمة انتظار واحدة، مما يلغي حالات السباق.
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 يتيح تشغيل مهام متعددة في قائمة انتظار متزامنة وتلقي إشعار عند اكتمال جميعها. هذا مفيد عند تحميل بيانات لشاشة الملف الشخصي.
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 في قائمة انتظار تسلسلية هو الخطأ الأكثر شيوعًا. إذا استدعت مهمة في قائمة انتظار تسلسلية queue.sync على نفس القائمة، يُحظر الخيط إلى الأبد. تنتظر قائمة الانتظار اكتمال المهمة الحالية، وتنتظر المهمة اكتمال استدعاء sync — جمود متبادل كلاسيكي.
جميع العمليات مع UIKit يجب أن تتم على الخيط الرئيسي. يكتشف Xcode هذه الأخطاء في وضع Debug عبر Main Thread Checker. في إصدارات Release، تؤدي إلى سلوك غير متوقع: الرسوم المتحركة لا تبدأ، واجهة المستخدم لا تتحديث، وقد تحدث أعطال.
إنشاء مئات قوائم الانتظار المخصصة بدلاً من استخدام قوائم الانتظار العالمية هو نمط معاكس. تستهلك كل قائمة انتظار موارد النظام. لمعظم المهام، تكفي قوائم الانتظار المتزامنة العالمية بمستويات QoS مختلفة وقائمة أو اثنتين تسلسليتين لمزامنة البيانات المشتركة.
عند تنفيذ مهام حلقية كثيفة الموارد في قائمة انتظار خلفية بدون autoreleasepool، ينمو استخدام الذاكرة حتى نهاية الحلقة بأكملها. يحرر ARC الكائنات فقط عند الخروج من autorelease pool. لفّ تكرارات الحلقة في autoreleasepool { } لتحرير الذاكرة في الوقت المناسب.
الأسئلة الشائعة
OperationQueue مبنية فوق GCD ولكنها توفر API أعلى مستوى مع تبعيات العمليات و KVO ودعم الإلغاء. DispatchQueue هي قائمة انتظار منخفضة المستوى لمهام async بسيطة بدون إدارة تبعيات.
GCD لا يدعم إيقاف مهمة قيد التشغيل. طريقة suspend() توقف فقط المهام الجديدة؛ المهمة الحالية تُنفذ حتى النهاية. الإلغاء يتطلب فحصًا يدويًا للعلامة داخل كود المهمة.
لطلب رئيسي مع عرض فوري للنتيجة — .userInitiated. للتحميل المسبق للبيانات — .utility. للمزامنة الخلفية — .background.
GCD لا يحدد عدد الخيوط. مجموعة الخيوط تتوسع ديناميكيًا تحت الحمل، مع مراعاة نوى المعالج والحمل الحالي و QoS لكل مهمة. العدد الأقصى مقيد بالنظام.
UIKit ليس آمنًا للخيوط — يجب استدعاء جميع فئاته فقط من الخيط الرئيسي. المخالفة تسبب سلوكًا غير متوقع، تحديثات مفقودة، وأعطال في الإنتاج.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا