OperationQueue — این چیست، Operation و مدیریت وظایف

نویسنده: IT Sectr منتشر شده: 2026-03-16 زمان مطالعه: 8 دقیقه

OperationQueue یک صف وظایف سطح بالا در iOS و macOS است که بر روی Grand Central Dispatch ساخته شده است. به گفته Apple Developer Documentation, 2026، OperationQueue نمونه‌های Operation — اشیایی که یک واحد کار را کپسوله می‌کنند — مدیریت می‌کند. برخلاف DispatchQueue، OperationQueue از وابستگی‌های بین عملیات‌ها، اولویت‌ها، مشاهده KVO و لغو وظایف در حال اجرا پشتیبانی می‌کند. OperationQueue به طور خودکار استخر رشته‌ها را مدیریت کرده و عملیات‌ها را بر اساس منابع موجود سیستم توزیع می‌کند.

نکات اصلی

  • OperationQueue — صف سطح بالا با پشتیبانی از وابستگی‌های بین عملیات‌ها
  • Operation — کلاس انتزاعی برای کپسوله‌سازی واحد کار با وضعیت
  • BlockOperation — پیاده‌سازی ساده‌شده Operation برای یک بلوک کد
  • وابستگی‌ها ترتیب اجرا را مشخص می‌کنند: عملیات B بعد از A اجرا می‌شود
  • لغو عملیات‌ها از طریق ویژگی سازگار با KVO isCancelled پشتیبانی می‌شود

OperationQueue و Operation چیست

OperationQueue کلاسی از فریمورک Foundation است که اجرای اشیاء Operation را مدیریت می‌کند. برخلاف DispatchQueue، OperationQueue نیاز به مشخص کردن صریح حالت serial یا concurrent ندارد — تعداد عملیات‌های همزمان توسط ویژگی maxConcurrentOperationCount تنظیم می‌شود. مقدار 1 صف را به sequential تبدیل می‌کند، هر مقدار دیگر آن را به concurrent تبدیل می‌کند.

Operation یک کلاس انتزاعی است که یک واحد کار را نشان می‌دهد. هر عملیات دارای وضعیت است: ready، executing، finished یا cancelled. وضعیت‌ها با KVO (Key-Value Observing) سازگار هستند که امکان واکنش به تغییرات — به‌روزرسانی UI هنگام اتمام عملیات — را فراهم می‌کند. Operation به طور خودکار پرچم‌های isExecuting و isFinished را مدیریت می‌کند.

به گفته Apple (2026)، OperationQueue در زیرساخت خود از GCD استفاده می‌کند، اما قابلیت‌هایی را اضافه می‌کند که در DispatchQueue در دسترس نیستند: وابستگی‌ها، اولویت‌ها و لغو عملیات‌ها. اگر برنامه به حالت پس‌زمینه برود، OperationQueue اجرا را متوقف می‌کند و هنگام بازگشت از سر می‌گیرد. OperationQueue همچنین به طور خودکار تعداد هسته‌های پردازنده را در نظر گرفته و تعداد بهینه رشته‌ها را انتخاب می‌کند.

چرخه حیات Operation

هر عملیات چهار وضعیت را طی می‌کند: pending (در انتظار)، ready (آماده اجرا)، executing (در حال اجرا) و finished (تکمیل شده). وضعیت cancelled می‌تواند در هر مرحله قبل از اتمام رخ دهد. انتقال بین وضعیت‌ها از طریق KVO ردیابی می‌شود — این اساس به‌روزرسانی واکنش‌گرای UI است. OperationQueue به طور خودکار عملیات‌های تکمیل شده را از صف حذف می‌کند و به عملیات‌های وابسته اطلاع می‌دهد که پیش‌نیازشان برآورده شده است و اجرای آنها را آغاز می‌کند.

Operation و BlockOperation: پیاده‌سازی وظایف

Operation یک کلاس انتزاعی است که نیاز به بازنویسی متد main() یا start() دارد. در متد main() کد وظیفه قرار می‌گیرد و وضعیت isExecuting و isFinished به طور خودکار مدیریت می‌شود. برای عملیات‌های ناهمزمان نیاز به بازنویسی start() و مدیریت دستی پرچم‌های وضعیت است.

BlockOperation پیاده‌سازی مشخصی از Operation است که یک یا چند بلوک کد را اجرا می‌کند. BlockOperation زمانی concurrent می‌شود که چندین بلوک از طریق addExecutionBlock() به آن اضافه شود. عملیات تنها پس از اجرای تمام بلوک‌های اضافه شده تکمیل می‌شود. BlockOperation جایگزین مناسبی برای وظایف ساده بدون نیاز به وراثت است.

ویژگیOperationBlockOperation
نوع کلاسانتزاعیمشخص
وراثتالزامیغیرضروری
ناهمزمانیمدیریت دستی KVOخودکار
بلوک‌های کدیکی در main()یک یا چند
کاربردوظایف پیچیده با وضعیتوظایف ساده یک‌باره
مناسب برایوابستگی‌ها، لغو، پیشرفتبلوک‌های سریع، completion
حافظهبیشتر به دلیل KVO و وضعیتحداقل، سبک

ایجاد Operation سفارشی

برای ایجاد یک عملیات سفارشی از Operation ارث‌بری کنید و main() را بازنویسی کنید. در داخل، قبل از عملیات‌های پرهزینه، پرچم isCancelled را بررسی کنید تا لغو سریع تضمین شود. این برای دانلود فایل‌های بزرگ یا پردازش دسته‌ای داده‌ها حیاتی است. انتخاب بین Operation و BlockOperation به پیچیدگی وظیفه بستگی دارد: برای اقدامات ساده یک‌باره BlockOperation کافی است، برای منطق قابل استفاده مجدد با وضعیت — ارث‌بری از Operation.

وابستگی‌ها و اولویت‌های عملیات

وابستگی‌ها مزیت کلیدی OperationQueue نسبت به DispatchQueue هستند. متد addDependency(_:) مشخص می‌کند که عملیات B تنها پس از اتمام عملیات A اجرا شود. وابستگی‌ها یک directed acyclic graph (DAG) تشکیل می‌دهند: هنگام اضافه شدن وابستگی چرخه‌ای، صف آن را نادیده می‌گیرد و عملیات‌ها اجرا نمی‌شوند.

اولویت عملیات با ویژگی queuePriority با مقادیر .veryLow، .low، .normal، .high، .veryHigh تنظیم می‌شود. اولویت بر ترتیب شروع در میان عملیات‌های ready تأثیر می‌گذارد، اما وابستگی‌ها را لغو نمی‌کند. OperationQueue ابتدا وابستگی‌ها، سپس اولویت را در میان عملیات‌های موجود در نظر می‌گیرد.

مثال عملی وابستگی‌ها

سناریوی معمول — بارگیری داده‌های پروفایل: ابتدا کاربر را بارگیری می‌کنیم، سپس بر اساس id او دوستان و پست‌ها را بارگیری می‌کنیم. تنظیم وابستگی بین بارگیری کاربر و بارگیری دوستان ترتیب صحیح را بدون completion handler تو در تو تضمین می‌کند.

محدود کردن هم‌روندی

ویژگی maxConcurrentOperationCount تعداد عملیات‌های همزمان اجرا را محدود می‌کند. مقدار 1 یک صف sequential ایجاد می‌کند، مقدار پیش‌فرض (NSOperationQueueDefaultMaxConcurrentOperationCount) — بهینه سیستمی، وابسته به بار فعلی دستگاه است. تنظیم صحیح این پارامتر از مصرف بیش از حد منابع جلوگیری می‌کند: برای بارگیری تصاویر 4-6 عملیات concurrent کافی است، برای وظایف CPU-intensive — تعداد هسته‌های پردازنده.

OperationQueue vs DispatchQueue: مقایسه

انتخاب بین OperationQueue و DispatchQueue به پیچیدگی وظیفه بستگی دارد. DispatchQueue ابزاری سبک برای فراخوانی‌های async ساده است. OperationQueue راه‌حل سنگین‌تری برای سناریوهای پیچیده با وظایف متعدد به هم مرتبط است. Apple توصیه می‌کند با DispatchQueue شروع کنید و فقط در صورت نیاز به وابستگی‌ها یا لغو به OperationQueue بروید. برای اکثر پروژه‌های iOS ترکیب هر دو ابزار تعادل بهینه‌ای از کارایی و انعطاف‌پذیری ارائه می‌دهد.

  • DispatchQueue — سبک، سریع، بدون سربار اشیاء Operation
  • OperationQueue — پشتیبانی از وابستگی‌ها، لغو، KVO و اولویت‌ها
  • DispatchQueue — ایده‌آل برای وظایف ساده async/asyncAfter و همگام‌سازی از طریق serial
  • OperationQueue — ضروری برای الگوریتم‌های گام‌به‌گام با مراحل متوالی
  • DispatchQueue — ادغام با Swift Concurrency (async/await) از طریق Continuation

به گفته Ray Wenderlich (2025)، در پروژه‌های بزرگ iOS از OperationQueue برای بارگیری محتوا با پیشرفت و لغو استفاده می‌شود و از DispatchQueue برای سایر عملیات‌های async. نسبت تقریباً 20 به 80 به نفع DispatchQueue است.

نمونه کدهای OperationQueue در Swift

سه مثال را بررسی می‌کنیم: BlockOperation ساده، Operation سفارشی با وابستگی‌ها و عملیات قابل لغو برای بارگیری داده‌ها.

BlockOperation با completion

ساده‌ترین حالت — اجرای بلوک در 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 اجرا شود. این نیاز به callback تو در تو را از بین می‌برد.

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() باید به طور مستقل isCancelled را بررسی کرده و در صورت لزوم پایان یابد. این تصمیم معماری Apple است — به توسعه‌دهنده اجازه می‌دهد در زمان لغو منابع را به درستی آزاد کند.

مشاهده KVO بر روی ویژگی‌های isFinished و isExecuting امکان واکنش به اتمام عملیات‌ها بدون callback صریح را فراهم می‌کند. OperationQueue به طور خودکار عملیات‌های تکمیل شده را از صف حذف می‌کند، اما آنها تا زمانی که ارجاعات قوی به آنها وجود دارد در حافظه باقی می‌مانند. KVO اساس ادغام OperationQueue با فریمورک‌های واکنش‌گرا مانند RxSwift یا Combine است.

مدیریت لغو از طریق KVO

اشتراک در isCancelled از طریق KVO امکان به‌روزرسانی UI را هنگام لغو عملیات فراهم می‌کند — مثلاً نمایش placeholder به جای بارگیری لغو شده. ویژگی isCancelled سازگار با KVO است که آن را برای pipeline واکنش‌گرا مناسب می‌کند.

بهترین روش‌های کار با OperationQueue

عملیات‌ها را در تعداد زیاد ایجاد نکنید — هر Operation یک شیء جداگانه در حافظه است. اگر وظیفه کوتاه است و نیازی به وابستگی ندارد، مستقیماً از DispatchQueue استفاده کنید. OperationQueue فقط برای سناریوهای پیچیده با وابستگی‌های آشکار، لغو و نظارت بر پیشرفت توجیه‌پذیر است.

isCancelled را قبل از عملیات‌های پرهزینه بررسی کنید در داخل متد main(). در موارد دانلود فایل یا پردازش تصاویر، بررسی پس از هر مرحله مهم پاسخ سریع به لغو را تضمین می‌کند. از if isCancelled { return } در ابتدای main() و پس از هر عملیات بزرگ استفاده کنید.

completionBlock را به درستی مدیریت کنید. ویژگی completionBlock عملیات پس از اتمام main() فراخوانی می‌شود، حتی اگر عملیات لغو شده باشد. isCancelled را در داخل completionBlock بررسی کنید تا UI را با داده‌های اشتباه به‌روزرسانی نکنید. OperationQueue.main — صف thread-safe برای عملیات UI، مشابه DispatchQueue.main.

از وابستگی‌های چرخه‌ای خودداری کنید — آنها باعث می‌شوند هیچ‌یک از عملیات‌های موجود در چرخه هرگز اجرا نشوند. OperationQueue چرخه‌ها را به طور خودکار تشخیص نمی‌دهد: اگر A به B و B به A وابسته باشد، هر دو برای همیشه در وضعیت ready باقی می‌مانند. گراف وابستگی را از قبل برنامه‌ریزی کنید.

سوالات متداول

تفاوت OperationQueue با DispatchQueue چیست؟

OperationQueue بر روی GCD ساخته شده و وابستگی‌ها، اولویت‌ها، KVO و لغو عملیات‌ها را اضافه می‌کند. DispatchQueue ابزار سبک‌تری برای وظایف async ساده بدون این قابلیت‌ها است.

چگونه صف را ترتیبی کنیم؟

ویژگی maxConcurrentOperationCount را روی 1 تنظیم کنید. این OperationQueue را با حفظ تمام مزایا — وابستگی‌ها، اولویت‌ها و لغو — به صف sequential تبدیل می‌کند.

آیا می‌توان عملیات در حال اجرا را لغو کرد؟

متد cancel() پرچم isCancelled را تنظیم می‌کند، اما متد main() در حال اجرا را متوقف نمی‌کند. کد عملیات باید خود isCancelled را بررسی کرده و پایان یابد. لغو فقط برای عملیات‌های pending و ready کار می‌کند.

کی باید از Operation به جای BlockOperation استفاده کرد؟

زمانی که مدیریت وضعیت، ناهمزمانی یا استفاده مجدد از منطق مورد نیاز است، باید از Operation ارث‌بری کرد. BlockOperation برای وظایف ساده یک‌باره بدون وراثت مناسب است.

آیا OperationQueue رشته اصلی را مسدود می‌کند؟

خیر، مگر اینکه متد waitUntilFinished با پارامتر true در رشته اصلی فراخوانی شود. عملیات‌ها به طور پیش‌فرض در رشته‌های پس‌زمینه اجرا می‌شوند و نتیجه از طریق OperationQueue.main بازگردانده می‌شود.

خلاصه

  • OperationQueue — صف سطح بالا با وابستگی‌ها، اولویت‌ها و لغو عملیات‌ها
  • Operation — کلاس انتزاعی برای کپسوله‌سازی کار با وضعیت سازگار با KVO
  • BlockOperation — پیاده‌سازی ساده‌شده برای یک یا چند بلوک کد
  • وابستگی‌ها ترتیب اجرا را بین عملیات‌ها از طریق گراف بدون چرخه مشخص می‌کنند
  • لغو نیاز به بررسی دستی isCancelled در داخل متد main() عملیات دارد
  • maxConcurrentOperationCount = 1 صف را به حالت sequential تبدیل می‌کند
  • OperationQueue vs DispatchQueue — فقط در صورت نیاز به وابستگی‌ها یا KVO انتخاب کنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید