قوائم المهام في C#: دليل شامل للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

العمل مع قوائم المهام في C#: للمبتدئين

\n\n

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

\n\n

في هذه المقالة، سنشرح من خلال أمثلة عملية كيفية عمل قوائم المهام في C# (.NET)، بدءًا من الفئات الأساسية وصولاً إلى الحلول الآمنة للخيوط للتطبيقات متعددة الخيوط.

\n\n

ما هي قائمة المهام ولماذا نحتاجها؟

\n\n

القائمة (Queue) هي هيكل بيانات يعمل وفق مبدأ FIFO (First In, First Out): العنصر المضاف أولاً سيتم معالجته أولاً. في سياق المهام، هذا يعني أنه يمكننا وضع مهمة في القائمة ومعالجتها لاحقًا عندما تصبح الموارد متاحة.

\n\n

السيناريوهات الرئيسية لاستخدام قوائم المهام:

\n
    \n
  • المعالجة الخلفية (إرسال البريد الإلكتروني، إنشاء التقارير)
  • \n
  • موازنة التحميل (توزيع المهام بين خيوط العمل)
  • \n
  • تخزين الطلبات مؤقتًا (عندما لا يستطيع النظام معالجة جميع الطلبات فورًا)
  • \n
  • تسجيل السجلات غير المتزامن (كتابة السجلات دون إبطاء التطبيق الرئيسي)
  • \n
\n\n

الفئة الأساسية Queue<T> في C#

\n\n

في .NET، توجد فئة مدمجة Queue<T> من مساحة الأسماء System.Collections.Generic. دعنا نلقي نظرة على مثال بسيط:

\n\n
using System;\nusing System.Collections.Generic;\n\npublic class SimpleQueueExample\n{\n    public static void Main()\n    {\n        // إنشاء قائمة من السلاسل النصية\n        Queue<string> taskQueue = new Queue<string>();\n\n        // إضافة المهام\n        taskQueue.Enqueue("إرسال بريد إلكتروني للعميل");\n        taskQueue.Enqueue("إنشاء تقرير");\n        taskQueue.Enqueue("تحديث الذاكرة المؤقتة");\n\n        Console.WriteLine($"عدد المهام في القائمة: {taskQueue.Count}");\n\n        // معالجة المهام بالترتيب\n        while (taskQueue.Count > 0)\n        {\n            string task = taskQueue.Dequeue();\n            Console.WriteLine($"معالجة: {task}");\n        }\n\n        Console.WriteLine($"القائمة فارغة: {taskQueue.Count == 0}");\n    }\n}
\n\n

الطرق الأساسية لـ Queue<T>:

\n
    \n
  • Enqueue(T item) - يضيف عنصرًا إلى نهاية القائمة
  • \n
  • Dequeue() - يستخرج ويزيل عنصرًا من بداية القائمة
  • \n
  • Peek() - يعيد العنصر الأول دون إزالته
  • \n
  • Count - عدد العناصر في القائمة
  • \n
\n\n

هام: Queue<T> ليس آمنًا للخيوط. إذا قرأت وكتبت عدة خيوط في القائمة في نفس الوقت، ستحدث أخطاء. للسيناريوهات متعددة الخيوط، استخدم ConcurrentQueue<T>.

\n\n

القائمة الآمنة للخيوط: ConcurrentQueue<T>

\n\n

في التطبيقات الحقيقية، تُستخدم قوائم المهام دائمًا تقريبًا في سياق متعدد الخيوط. لهذا، توجد في .NET فئة ConcurrentQueue<T> من مساحة الأسماء System.Collections.Concurrent.

\n\n
using System;\nusing System.Collections.Concurrent;\nusing System.Threading.Tasks;\n\npublic class ConcurrentQueueExample\n{\n    public static void Main()\n    {\n        ConcurrentQueue<string> taskQueue = new ConcurrentQueue<string>();\n\n        // المهمة 1: إضافة العناصر (Producer)\n        Task producer = Task.Run(() =>\n        {\n            for (int i = 1; i <= 10; i++)\n            {\n                taskQueue.Enqueue($"المهمة #{i}");\n                Console.WriteLine($"تمت إضافة المهمة #{i}");\n                

المدونات

توصيات الكتب