OperationQueue — ما هي، Operation وإدارة المهام

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

OperationQueue هي قائمة مهام عالية المستوى في iOS و macOS مبنية فوق Grand Central Dispatch. وفقًا لوثائق Apple Developer، 2026، يدير OperationQueue مثيلات Operation — كائنات تغلف وحدة عمل. على عكس DispatchQueue، يدعم OperationQueue التبعيات بين العمليات والأولويات ومراقبة KVO وإلغاء المهام قيد التشغيل. يدير OperationQueue تلقائيًا مجموعة من الخيوط، موزعًا العمليات على موارد النظام المتاحة.

النقاط الرئيسية

  • OperationQueue — قائمة عالية المستوى مع دعم التبعيات بين العمليات
  • Operation — فئة مجردة لتغليف وحدة عمل مع حالة
  • BlockOperation — تنفيذ مبسط لـ Operation لكتلة برمجية واحدة
  • التبعيات تحدد ترتيب التنفيذ: العملية B تعمل بعد A
  • الإلغاء للعمليات مدعوم من خلال الخاصية isCancelled المتوافقة مع KVO

ما هي OperationQueue و Operation

OperationQueue هي فئة من إطار Foundation تدير تنفيذ كائنات Operation. على عكس DispatchQueue، لا تتطلب OperationQueue تحديد الوضع التسلسلي أو المتزامن بشكل صريح — يتم التحكم في عدد العمليات التي يتم تنفيذها في وقت واحد بواسطة الخاصية maxConcurrentOperationCount. القيمة 1 تجعل القائمة تسلسلية، وأي قيمة أخرى تجعلها متزامنة.

Operation هي فئة مجردة تمثل وحدة عمل. كل عملية لها حالة: ready أو executing أو finished أو cancelled. الحالات متوافقة مع KVO (مراقبة القيمة الرئيسية)، مما يسمح بالتفاعل مع التغييرات — على سبيل المثال، تحديث الواجهة عند اكتمال العملية. تدير Operation تلقائيًا العلامات isExecuting و isFinished.

وفقًا لشركة Apple (2026)، تستخدم OperationQueue GCD داخليًا ولكنها تضيف وظائف غير متوفرة في DispatchQueue: التبعيات والأولويات والإلغاء للعمليات. إذا دخل التطبيق الخلفية، تعلق OperationQueue التنفيذ وتستأنفه عند العودة. تراعي OperationQueue أيضًا تلقائيًا عدد أنوية المعالج وتختار العدد الأمثل من الخيوط.

دورة حياة Operation

تمر كل عملية بأربع حالات: pending (قيد الانتظار)، ready (جاهزة)، executing (قيد التنفيذ)، وfinished (مكتملة). يمكن أن تحدث حالة cancelled في أي مرحلة قبل الاكتمال. يتم تتبع انتقالات الحالة عبر KVO — وهذا هو الأساس للتحديثات التفاعلية للواجهة. تزيل OperationQueue تلقائيًا العمليات المكتملة من القائمة وتخطر العمليات التابعة بأن المتطلب الأساسي قد تم استيفاؤه، مما يؤدي إلى تشغيل تنفيذها.

Operation و BlockOperation: تنفيذ المهام

Operation هي فئة مجردة تتطلب تجاوز الطريقة main() أو start(). يتم وضع كود المهمة في الطريقة main()، ويتم إدارة حالتي isExecuting و isFinished تلقائيًا. للعمليات غير المتزامنة، يلزم تجاوز start() وإدارة علامات الحالة يدويًا.

BlockOperation هو تنفيذ ملموس لـ Operation ينفذ كتلة برمجية واحدة أو أكثر. يصبح BlockOperation متزامنًا إذا أضفت عدة كتل عبر addExecutionBlock(). تكتمل العملية فقط بعد تنفيذ جميع الكتل المضافة. BlockOperation هو بديل مناسب للمهام البسيطة دون وراثة.

الخاصيةOperationBlockOperation
نوع الفئةمجردةملموسة
الوراثةمطلوبةغير مطلوبة
عدم التزامنإدارة يدوية لـ KVOتلقائية
كتل برمجيةواحدة في main()واحدة أو عدة
الاستخداممهام معقدة مع حالةمهام بسيطة لمرة واحدة
مناسب لـالتبعيات، الإلغاء، التقدمكتل سريعة، الإكمال
الذاكرةأعلى بسبب KVO والحالةأدنى، خفيفة الوزن

إنشاء Operation مخصصة

لإنشاء عملية مخصصة، قم باشتقاق فئة من Operation وتجاوز main(). في الداخل، تحقق من العلامة isCancelled قبل العمليات المكلفة لضمان إلغاء سريع. هذا أمر بالغ الأهمية لتنزيل الملفات الكبيرة أو معالجة البيانات على دفعات. الاختيار بين Operation و BlockOperation يعتمد على تعقيد المهمة: للإجراءات البسيطة لمرة واحدة، يكفي BlockOperation؛ للمنطق القابل لإعادة الاستخدام مع الحالة، قم باشتقاق فئة من Operation.

التبعيات والأولويات للعمليات

التبعيات هي الميزة الرئيسية لـ OperationQueue مقارنة بـ DispatchQueue. تحدد الطريقة addDependency(_:) أن العملية B يتم تنفيذها فقط بعد اكتمال العملية A. تشكل التبعيات رسمًا بيانيًا موجهًا غير دائري (DAG): إذا تمت إضافة تبعية دائرية، تتجاهلها القائمة ولا تبدأ العمليات.

أولوية العملية يتم تعيينها عبر الخاصية queuePriority بالقيم: .veryLow، .low، .normal، .high، .veryHigh. تؤثر الأولوية على ترتيب البدء بين العمليات الجاهزة ولكنها لا تلغي التبعيات. OperationQueue تحل التبعيات أولاً، ثم تطبق الأولوية بين العمليات المتاحة.

مثال عملي على التبعيات

سيناريو نموذجي — تحميل بيانات الملف الشخصي: أولاً تحميل المستخدم، ثم بناءً على معرفه تحميل الأصدقاء والمنشورات. تعيين تبعية بين تحميل المستخدم وتحميل الأصدقاء يضمن الترتيب الصحيح دون معالجات إكمال متداخلة.

الحد من التزامن

الخاصية maxConcurrentOperationCount تحد من عدد العمليات التي يتم تنفيذها في وقت واحد. القيمة 1 تنشئ قائمة تسلسلية، القيمة الافتراضية (NSOperationQueueDefaultMaxConcurrentOperationCount) هي الأمثل للنظام وتعتمد على الحمل الحالي للجهاز. التكوين المناسب لهذه المعلمة يمنع الاستهلاك المفرط للموارد: لتحميل الصور، 4–6 عمليات متزامنة كافية؛ للمهام المكثفة لوحدة المعالجة المركزية، استخدم عدد أنوية المعالج.

OperationQueue vs DispatchQueue: مقارنة

الاختيار بين OperationQueue و DispatchQueue يعتمد على تعقيد المهمة. DispatchQueue هي أداة خفيفة للاستدعاءات غير المتزامنة البسيطة. OperationQueue هي حل أثقل للسيناريوهات المعقدة مع العديد من المهام المترابطة. توصي Apple بالبدء بـ DispatchQueue والانتقال إلى OperationQueue فقط عند الحاجة إلى التبعيات أو الإلغاء. لمعظم مشاريع iOS، مزيج من كلا الأداتين يعطي توازنًا أمثل بين الأداء والمرونة.

  • DispatchQueue — خفيفة، سريعة، بدون عبء كائنات Operation
  • OperationQueue — تدعم التبعيات، الإلغاء، KVO والأولويات
  • DispatchQueue — مثالية لمهام async/asyncAfter البسيطة والمزامنة التسلسلية
  • OperationQueue — لا غنى عنها للخوارزميات خطوة بخطوة مع مراحل تسلسلية
  • DispatchQueue — تتكامل مع Swift Concurrency (async/await) عبر Continuation

وفقًا لـ Ray Wenderlich (2025)، في مشاريع iOS الكبيرة، يتم استخدام OperationQueue لتحميل المحتوى مع التقدم والإلغاء، بينما يتم استخدام DispatchQueue لجميع العمليات غير المتزامنة الأخرى. النسبة حوالي 20 إلى 80 لصالح DispatchQueue.

أمثلة برمجية مع OperationQueue في Swift

دعنا نلقي نظرة على ثلاثة أمثلة: BlockOperation بسيط، Operation مخصصة مع تبعيات، وعملية قابلة للإلغاء لتحميل البيانات.

BlockOperation مع الإكمال

أبسط حالة — تنفيذ كتلة على OperationQueue ومعالجة النتيجة عبر completionBlock. كل Operation لها خاصية completionBlock مدمجة، يتم استدعاؤها بعد انتهاء main().

swift
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
    let data = NetworkService.fetchData()
    OperationQueue.main.addOperation {
        self.updateUI(data)
    }
}
queue.addOperation(operation)

التبعيات بين العمليات

التبعية تضمن أن parseOperation تبدأ فقط بعد اكتمال downloadOperation. هذا يلغي الحاجة إلى عمليات استدعاء متداخلة.

swift
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)

let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)

عملية مخصصة قابلة للإلغاء

قم بتجاوز main() مع فحوصات دورية لـ isCancelled. هذا يسمح للعملية بالتوقف فورًا عند الإلغاء، دون انتظار اكتمال عملية مكلفة.

swift
class ImageLoadOperation: Operation {
    override func main() {
        guard !self.isCancelled else { return }
        let image = self.downloadImage()
        guard !self.isCancelled else { return }
        OperationQueue.main.addOperation { self.display(image) }
    }
}

إلغاء العمليات ومراقبة KVO

إلغاء العملية يعيّن العلامة isCancelled إلى true، لكنه لا يوقف الطريقة main() قيد التشغيل. يجب أن يتحقق الكود داخل main() من isCancalled بنفسه وينهي عند الضرورة. هذا قرار معماري من Apple — يسمح للمطور بتحرير الموارد بشكل صحيح عند الإلغاء.

مراقبة KVO للخاصيتين isFinished و isExecuting تسمح بالتفاعل مع اكتمال العمليات دون استدعاءات صريحة. تزيل OperationQueue تلقائيًا العمليات المكتملة من القائمة، لكنها تبقى في الذاكرة طالما هناك مراجع قوية لها. KVO هي الأساس لدمج OperationQueue مع الأطر التفاعلية مثل RxSwift أو Combine.

معالجة الإلغاء عبر KVO

الاشتراك في isCancelled عبر KVO يسمح بتحديث الواجهة عند إلغاء العملية — على سبيل المثال، إظهار عنصر نائب بدلاً من تحميل تم إلغاؤه. الخاصية isCancelled متوافقة مع KVO، مما يجعلها ملائمة للخطوط التفاعلية.

أفضل الممارسات للعمل مع OperationQueue

لا تنشئ أعدادًا كبيرة من العمليات — كل Operation هي كائن منفصل في الذاكرة. إذا كانت المهمة قصيرة ولا تتطلب تبعيات، استخدم DispatchQueue مباشرة. OperationQueue مبررة للسيناريوهات المعقدة مع تبعيات صريحة وإلغاء ومراقبة التقدم.

تحقق من isCancelled قبل العمليات المكلفة داخل الطريقة main(). في حالات تنزيل الملفات أو معالجة الصور، التحقق بعد كل خطوة مهمة يضمن استجابة سريعة للإلغاء. استخدم if isCancelled { return } في بداية main() وبعد كل عملية رئيسية.

أدر completionBlock بشكل صحيح. يتم استدعاء خاصية completionBlock للعملية بعد انتهاء main()، حتى إذا تم إلغاء العملية. تحقق من isCancelled داخل completionBlock لتجنب تحديث الواجهة ببيانات خاطئة. OperationQueue.main هي قائمة آمنة للخيوط لعمليات الواجهة، مشابهة لـ DispatchQueue.main.

تجنب التبعيات الدائرية — تؤدي إلى عدم بدء أي من العمليات في الدورة أبدًا. لا تكتشف OperationQueue الدورات تلقائيًا: إذا كانت A تعتمد على B و B تعتمد على A، فستظل كلتاهما في حالة ready إلى الأبد. خطط للرسم البياني للتبعيات مسبقًا.

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

كيف تختلف OperationQueue عن DispatchQueue؟

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

كيف أجعل القائمة تسلسلية؟

اضبط الخاصية maxConcurrentOperationCount على 1. هذا يحول OperationQueue إلى قائمة تسلسلية مع الاحتفاظ بجميع المزايا — التبعيات والأولويات والإلغاء.

هل يمكن إلغاء عملية قيد التشغيل؟

الطريقة cancel() تعيّن العلامة isCancelled لكنها لا توقف الطريقة main() قيد التنفيذ. يجب أن يتحقق كود العملية من isCancelled بنفسه وينهي. الإلغاء يعمل فقط للعمليات المعلقة والجاهزة.

متى يجب استخدام Operation بدلاً من BlockOperation؟

يجب اشتقاق فئة من Operation عندما تحتاج إدارة حالة أو عدم تزامن أو إعادة استخدام المنطق. BlockOperation مناسب للمهام البسيطة لمرة واحدة دون وراثة.

هل تحجب OperationQueue الخيط الرئيسي؟

لا، ما لم تستدع waitUntilFinished مع المعامل true على الخيط الرئيسي. يتم تنفيذ العمليات على خيوط خلفية افتراضيًا، ويتم إرجاع النتائج عبر OperationQueue.main.

الملخص

  • OperationQueue — قائمة عالية المستوى مع تبعيات وأولويات وإلغاء عمليات
  • Operation — فئة مجردة لتغليف العمل مع حالة متوافقة مع KVO
  • BlockOperation — تنفيذ مبسط لكتلة برمجية واحدة أو أكثر
  • التبعيات تحدد ترتيب التنفيذ بين العمليات عبر رسم بياني بدون دورات
  • الإلغاء يتطلب فحصًا يدويًا لـ isCancelled داخل الطريقة main() للعملية
  • maxConcurrentOperationCount = 1 يحول القائمة إلى وضع تسلسلي
  • OperationQueue vs DispatchQueue — اختر OperationQueue فقط عند الحاجة للتبعيات أو KVO

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

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

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

اقرأ أيضًا