البرمجة التفاعلية في C# (.NET): Rx.NET و IObservable

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

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

ابدأ الدورة

البرمجة التفاعلية في C# (.NET): دليل شامل مع Rx.NET

\n\n

البرمجة التفاعلية هي نموذج تطوير يركز على تدفقات البيانات غير المتزامنة ونشر التغييرات. في نظام C# (.NET)، الأداة الرئيسية لتنفيذ هذا النهج هي مكتبة Reactive Extensions (Rx.NET). تتيح لك العمل مع تسلسلات البيانات التي تتغير بمرور الوقت بنفس سهولة العمل مع المجموعات العادية عبر LINQ.

\n\n

في هذه المقالة، سنشرح المفاهيم الأساسية للبرمجة التفاعلية، ونستعرض المكونات الرئيسية لـ Rx.NET، ونقدم أمثلة عملية على الكود للموقع التعليمي PythonLib.

\n\n

المفاهيم الأساسية للبرمجة التفاعلية

\n\n

في جوهر Rx.NET توجد واجهتان:

\n
    \n
  • IObservable<T> — مصدر البيانات (تسلسل قابل للملاحظة) يمكنه إرسال عناصر أو أخطاء أو إشارة اكتمال.
  • \n
  • IObserver<T> — المشترك (مراقب) الذي يتلقى الإشعارات من المصدر: OnNext، OnError، OnCompleted.
  • \n
\n\n

الفكرة الأساسية: بدلاً من استقصاء المصدر (نموذج السحب)، يتفاعل المشترك مع الأحداث (نموذج الدفع). هذا مفيد بشكل خاص لمعالجة أحداث واجهة المستخدم، وطلبات الشبكة، وتدفقات البيانات من أجهزة الاستشعار، أو أي عمليات غير متزامنة أخرى.

\n\n

بدء العمل مع Rx.NET

\n\n

لاستخدام Rx.NET في مشروع C#، قم بتثبيت حزمة NuGet:

\n
dotnet add package System.Reactive
\n\n

مثال 1: إنشاء والاشتراك في observable

\n

لننشئ تسلسلًا بسيطًا من الأرقام يولد قيمًا مع تأخير:

\n
using System;\nusing System.Reactive.Linq;\nusing System.Threading.Tasks;\n\nclass Program\n{\n    static async Task Main()\n    {\n        var observable = Observable\n            .Interval(TimeSpan.FromSeconds(1)) // يولد 0, 1, 2... كل ثانية\n            .Take(5); // نأخذ أول 5 أرقام فقط\n\n        var subscription = observable.Subscribe(\n            onNext: number => Console.WriteLine($"تم الاستلام: {number}"),\n            onError: error => Console.WriteLine($"خطأ: {error.Message}"),\n            onCompleted: () => Console.WriteLine("اكتمل التدفق")\n        );\n\n        // ننتظر اكتمال التدفق\n        await Task.Delay(6000);\n        subscription.Dispose(); // إلغاء الاشتراك\n    }\n}
\n\n

مثال 2: التصفية والتحويل باستخدام LINQ

\n

يدعم Rx.NET جميع عوامل تشغيل LINQ القياسية، مما يجعل الكود موجزًا:

\n
var values = Observable.Range(1, 10);\n\nvar processed = values\n    .Where(x => x % 2 == 0) // الأرقام الزوجية فقط\n    .Select(x => x * 10)    // نضرب في 10\n    .Timestamp();           // نضيف طابعًا زمنيًا\n\nprocessed.Subscribe(x => Console.WriteLine($"[{x.Timestamp}] القيمة: {x.Value}"));
\n\n

الإمكانيات المتقدمة لـ Rx.NET

\n\n

دمج التدفقات

\n

يمكنك دمج عدة تسلسلات observable:

\n
var stream1 = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x => $"A{x}");\nvar stream2 = Observable.Interval(TimeSpan.FromSeconds(1.5)).Select(x => $"B{x}");\n\nvar merged = stream1.Merge(stream2); // دمج في تدفق واحد\nmerged.Take(6).Subscribe(Console.WriteLine);
\n\n

إدارة تعدد المهام

\n

يتيح Rx.NET التبديل بسهولة بين سياقات التنفيذ:

\n
var uiScheduler = new SynchronizationContextScheduler(SynchronizationContext.Current);\n\nObservable\n    .Interval(TimeSpan.FromSeconds(1))\n    .ObserveOn(uiScheduler) // نضمن التنفيذ في سلسلة واجهة المستخدم\n    .Subscribe(x => UpdateUI(x)); // تحديث الواجهة
\n\n

معالجة الأخطاء

\n

يوفر Rx.NET آليات قوية للتعافي من الأعطال:

\n
var faultyStream = Observable.Throw<int>(new Exception("خطأ!"));\n\nvar safeStr                    

توصيات