البرمجة غير المتزامنة في C#: دليل كامل عملي
البرمجة غير المتزامنة هي أحد المفاهيم الأساسية في التطوير الحديث باستخدام C# ومنصة .NET. فهي تتيح إنشاء تطبيقات سريعة الاستجابة لا تمنع تدفق التنفيذ أثناء انتظار العمليات الطويلة: قراءة الملفات، استعلامات قاعدة البيانات، استدعاءات HTTP. في هذا الدليل، سنشرح كيفية عمل عدم التزامن في C# من خلال أمثلة عملية باستخدام الكلمات المفتاحية async و await، بالإضافة إلى أفضل الممارسات.
ما هي البرمجة غير المتزامنة ولماذا نحتاجها؟
في البرمجة المتزامنة، يتم تنفيذ كل عملية بشكل تسلسلي. إذا استدعت إحدى الطرق، على سبيل المثال، تحميل بيانات من الشبكة، يتم حظر تدفق التنفيذ حتى اكتمال هذه العملية. يؤدي ذلك إلى "تجميد" الواجهة في تطبيقات سطح المكتب أو إلى استخدام غير فعال لموارد الخادم في تطبيقات الويب.
البرمجة غير المتزامنة تحل هذه المشكلة: لا يتم حظر الخيط، بل يُعاد إلى مجموعة الخيوط لمعالجة مهام أخرى. عند اكتمال العملية، يستأنف التنفيذ من النقطة التي توقف عندها.
المزايا الرئيسية لعدم التزامن في C#:
- استجابة واجهة المستخدم — لا يتجمد التطبيق أثناء العمليات الطويلة.
- قابلية توسع الخوادم — يمكن لخيط واحد خدمة العديد من الطلبات.
- استخدام فعال للموارد — تقليل فترات توقف الخيوط.
أساسيات async و await في C#
الكلمتان المفتاحيتان async و await هما سكر نحوي يبسط العمل مع العمليات غير المتزامنة. لنلق نظرة على مثال أساسي:
using System;using System.Net.Http;using System.Threading.Tasks;
public class AsyncExample{ public async Task<string> DownloadDataAsync(string url) { using (var client = new HttpClient()) { // await لا يحجب الخيط string result = await client.GetStringAsync(url); return result; } }
public async Task RunAsync() { Console.WriteLine("نبدأ التحميل..."); string data = await DownloadDataAsync("https://api.example.com/data"); Console.WriteLine($"تم التحميل: {data.Length} حرف"); }}شرح الكود:
- الطريقة موسومة بـ
async— وهذا يسمح باستخدامawaitداخلها. - نوع الإرجاع هو
Task<string>(أوTaskللطرق من نوع void). awaitيوقف تنفيذ الطريقة مؤقتًا حتى الحصول على النتيجة، لكنه لا يحجب الخيط.
هام: يمكن أيضًا جعل الطريقة Main في تطبيق وحدة التحكم C# 7.1+ غير متزامنة:
static async Task Main(string[] args){ var example = new AsyncExample(); await example.RunAsync();}العمل مع Task و Task<T>
النوع Task يمثل عملية غير متزامنة. يمكن أن يكون في حالات: معلق (Pending)، قيد التنفيذ (Running)، مكتمل (Completed)، مع خطأ (Faulted) أو ملغي (Canceled).
لنلق نظرة على إنشاء وتشغيل المهام يدويًا:
public async Task ProcessDataAsync(){ // إنشاء مهمة يتم تنفيذها في مجموعة الخيوط Task<int> task = Task.Run(() => { // محاكاة عمل طويل Task.Delay(2000).Wait(); return 42; });
// انتظار النتيجة int result = await task; Console.WriteLine($"النتيجة: {result}");}للتنفيذ المتوازي لمهام متعددة، استخدم Task.WhenAll:
public async Task DownloadMultipleAsync(){ var urls = new[] { "https://site1.com", "https://site2.com", "https://site3.com" }; var tasks =