DispatchQueue: ما هو، قائمة انتظار GCD وأساسيات تعدد المهام

المؤلف: IT Sectr نُشر: 2026-03-16 وقت القراءة: 8 دق

DispatchQueue هي قائمة انتظار أساسية لـ Grand Central Dispatch (GCD) لإدارة المهام غير المتزامنة في iOS و macOS. وفقًا لـ Apple Developer Documentation, 2026، DispatchQueue تُجرّد إدارة الخيوط من المطور عبر قوائم انتظار تسلسلية ومتزامنة. يوزع GCD المهام تلقائيًا على مجموعة خيوط النظام، مما يلغي الحاجة إلى إنشاء الخيوط وتدميرها يدويًا.

الخلاصة

  • DispatchQueue هي التجريد الرئيسي لـ GCD لتنفيذ الكود غير المتزامن في iOS
  • قائمة الانتظار التسلسلية تنفذ المهام بتسلسل صارم، مما يلغي حالات السباق
  • قائمة الانتظار المتزامنة تشغل عدة مهام بالتوازي عبر مجموعة خيوط النظام
  • QoS يحدد أولوية المهمة — من userInteractive إلى background
  • DispatchQueue.main هي قائمة الانتظار الوحيدة لتحديث UIKit على الخيط الرئيسي

ما هو DispatchQueue و Grand Central Dispatch

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 استخدام الخيوط من المجموعة، مما يقلل من الحمل الإضافي لإنشاء الخيوط.

هندسة 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 لا يزال يوفر وقت تنفيذ مقبول.

مثال على استخدام QoS

عند تحميل صورة للعرض الفوري، استخدم .userInitiated — المستخدم يتوقع النتيجة. للتحميل المسبق للشاشة التالية، .utility كافٍ. تتم مزامنة الخلفية مع الخادم باستخدام .background، مما يقلل التأثير على المهام النشطة.

DispatchGroup والإشارات: مزامنة المهام

DispatchGroup يسمح بتتبع اكتمال مجموعة من المهام. عندما تكتمل جميع المهام في المجموعة، يستدعي GCD معالج notify في قائمة الانتظار المحددة. هذا مفيد بشكل خاص عند تحميل موارد مستقلة متعددة — بيانات الملف الشخصي، قائمة الأصدقاء، والإعدادات — حيث يجب تحديث الواجهة فقط بعد استلام جميع البيانات.

يدعم DispatchGroup استدعاءًا متزامنًا wait()، يحظر الخيط الحالي حتى اكتمال جميع المهام. هذا مناسب عندما لا يمكن للكود الاستمرار بدون نتائج المجموعة. البديل غير المتزامن notify() يستدعي إغلاقًا في قائمة الانتظار المحددة بعد اكتمال جميع المهام، دون حظر الخيط المستدعي.

DispatchSemaphore للحد من التوازي

DispatchSemaphore يتحكم في الوصول إلى مورد عن طريق تحديد عدد الوصول المتزامن. سيمافور بقيمة ابتدائية 3 يسمح بتشغيل ما لا يزيد عن ثلاث مهام متوازية. استدعاء wait() يقلل العداد، signal() يزيده. إذا وصل العداد إلى الصفر، يُحظر الخيط حتى يتوفر مورد.

أمثلة كود مع DispatchQueue في Swift

لنلقِ نظرة على ثلاثة أمثلة عملية لاستخدام DispatchQueue في Swift. الأول يوضح استدعاء async أساسي مع العودة إلى الخيط الرئيسي، والثاني يظهر المزامنة عبر قائمة انتظار تسلسلية، والثالث يستخدم DispatchGroup للطلبات المتوازية.

استدعاء async أساسي مع العودة إلى main

DispatchQueue.main هي قائمة الانتظار التسلسلية للخيط الرئيسي، المخصصة حصريًا لعمليات واجهة المستخدم. استخدمها دائمًا لتحديث الواجهة بعد اكتمال العمل في الخلفية.

swift
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
    let data = self.fetchData()
    DispatchQueue.main.async {
        self.updateUI(with: data)
    }
}

قائمة انتظار تسلسلية لحماية مورد مشترك

إنشاء قائمة انتظار تسلسلية مخصصة بمعرف فريد يزامن الوصول إلى مصفوفة قابلة للتغيير. تمر جميع عمليات القراءة والكتابة عبر قائمة انتظار واحدة، مما يلغي حالات السباق.

swift
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 للطلبات المتوازية

DispatchGroup يتيح تشغيل مهام متعددة في قائمة انتظار متزامنة وتلقي إشعار عند اكتمال جميعها. هذا مفيد عند تحميل بيانات لشاشة الملف الشخصي.

swift
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()
}

الأخطاء الشائعة عند العمل مع DispatchQueue

الجمود (Deadlock) عند استدعاء sync في قائمة انتظار تسلسلية هو الخطأ الأكثر شيوعًا. إذا استدعت مهمة في قائمة انتظار تسلسلية queue.sync على نفس القائمة، يُحظر الخيط إلى الأبد. تنتظر قائمة الانتظار اكتمال المهمة الحالية، وتنتظر المهمة اكتمال استدعاء sync — جمود متبادل كلاسيكي.

تحديث واجهة المستخدم من خيط خلفي

جميع العمليات مع UIKit يجب أن تتم على الخيط الرئيسي. يكتشف Xcode هذه الأخطاء في وضع Debug عبر Main Thread Checker. في إصدارات Release، تؤدي إلى سلوك غير متوقع: الرسوم المتحركة لا تبدأ، واجهة المستخدم لا تتحديث، وقد تحدث أعطال.

الإفراط في إنشاء قوائم انتظار مخصصة

إنشاء مئات قوائم الانتظار المخصصة بدلاً من استخدام قوائم الانتظار العالمية هو نمط معاكس. تستهلك كل قائمة انتظار موارد النظام. لمعظم المهام، تكفي قوائم الانتظار المتزامنة العالمية بمستويات QoS مختلفة وقائمة أو اثنتين تسلسليتين لمزامنة البيانات المشتركة.

تجاهل autoreleasepool في الحلقات

عند تنفيذ مهام حلقية كثيفة الموارد في قائمة انتظار خلفية بدون autoreleasepool، ينمو استخدام الذاكرة حتى نهاية الحلقة بأكملها. يحرر ARC الكائنات فقط عند الخروج من autorelease pool. لفّ تكرارات الحلقة في autoreleasepool { } لتحرير الذاكرة في الوقت المناسب.

الأسئلة الشائعة

ما الفرق بين DispatchQueue و OperationQueue؟

OperationQueue مبنية فوق GCD ولكنها توفر API أعلى مستوى مع تبعيات العمليات و KVO ودعم الإلغاء. DispatchQueue هي قائمة انتظار منخفضة المستوى لمهام async بسيطة بدون إدارة تبعيات.

هل يمكن إيقاف مهمة في DispatchQueue قسرًا؟

GCD لا يدعم إيقاف مهمة قيد التشغيل. طريقة suspend() توقف فقط المهام الجديدة؛ المهمة الحالية تُنفذ حتى النهاية. الإلغاء يتطلب فحصًا يدويًا للعلامة داخل كود المهمة.

ما QoS الذي يجب اختياره لطلب الشبكة؟

لطلب رئيسي مع عرض فوري للنتيجة — .userInitiated. للتحميل المسبق للبيانات — .utility. للمزامنة الخلفية — .background.

كم عدد الخيوط التي تستخدمها قائمة الانتظار المتزامنة؟

GCD لا يحدد عدد الخيوط. مجموعة الخيوط تتوسع ديناميكيًا تحت الحمل، مع مراعاة نوى المعالج والحمل الحالي و QoS لكل مهمة. العدد الأقصى مقيد بالنظام.

لماذا DispatchQueue.main إلزامي لـ UIKit؟

UIKit ليس آمنًا للخيوط — يجب استدعاء جميع فئاته فقط من الخيط الرئيسي. المخالفة تسبب سلوكًا غير متوقع، تحديثات مفقودة، وأعطال في الإنتاج.

الملخص

  • DispatchQueue هي الأداة الرئيسية لـ Grand Central Dispatch للمهام غير المتزامنة في iOS و macOS
  • قائمة الانتظار التسلسلية تنفذ المهام بتسلسل، مما يلغي حالات السباق دون أقفال
  • قائمة الانتظار المتزامنة تشغل المهام بالتوازي عبر مجموعة خيوط النظام
  • QoS يحدد أولوية المهمة — من userInteractive إلى background
  • DispatchGroup يزامن مهام متوازية متعددة مع notify على الخيط الرئيسي
  • الجمود (Deadlock) عند sync في قائمة انتظار تسلسلية مشغولة هو خطأ حرج يتطلب الانتباه
  • الخيط الرئيسي إلزامي لـ UIKit — قم بتحديث الواجهة فقط عبر DispatchQueue.main

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا