البرمجة غير المتزامنة في Rust: دليل كامل مع أمثلة

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

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

ابدأ الدورة

البرمجة غير المتزامنة في Rust: من الأساسيات إلى التقنيات المتقدمة



تتطلب التطبيقات الحديثة أداءً عاليًا وكفاءة في التعامل مع عمليات الإدخال/الإخراج (I/O). تقدم Rust، المعروفة بسرعتها وأمانها، نموذجًا قويًا للبرمجة غير المتزامنة. في هذا الدليل، سنشرح بالتفصيل كيفية استخدام async/await، ومكتبة tokio، وأدوات أخرى لإنشاء برامج غير متزامنة سريعة وموثوقة.



ما هي البرمجة غير المتزامنة في Rust؟



البرمجة غير المتزامنة هي نموذج يسمح بتنفيذ مهام متعددة في وقت واحد دون إنشاء خيوط (threads) من نظام التشغيل. بدلاً من حظر الخيط أثناء انتظار الإدخال/الإخراج (قراءة ملف، طلب HTTP)، تقوم الدالة غير المتزامنة "بالتعليق" ونقل التحكم إلى مهام أخرى. تنفذ Rust ذلك من خلال Futures وآلية async/await.



المفاهيم الأساسية:

  • Future — trait يمثل عملية غير متزامنة قد تكتمل لاحقًا.
  • async/await — سكر نحوي (syntactic sugar) للعمل مع Futures.
  • Runtime (المنفذ) — بيئة تنفيذ تستقصي Futures وتشغلها. الأكثر شهرة هو Tokio.
  • Task — وحدة عمل خفيفة الوزن، يديرها Runtime.


أول برنامج غير متزامن في Rust



للبدء، أضف التبعيات في ملف Cargo.toml:



[dependencies]tokio = { version = "1", features = ["full"] }reqwest = { version = "0.12", features = ["json"] }serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"


الآن لنكتب عميل HTTP غير متزامن بسيط:



use reqwest;use serde::Deserialize;

#[derive(Deserialize, Debug)]struct Todo { userId: u32, id: u32, title: String, completed: bool,}

#[tokio::main]async fn main() -> Result<(), Box> { // طلب GET غير متزامن let response = reqwest::get("https://jsonplaceholder.typicode.com/todos/1") .await?; // await يعلق التنفيذ حتى يصل الرد let todo: Todo = response.json().await?; // إلغاء التسلسل غير المتزامن println!("تم استلام المهمة: {:#?}", todo); Ok(())}


لاحظ الماكرو #[tokio::main] — فهو يحول الدالة العادية main إلى نقطة دخول غير متزامنة، مشغلاً Runtime الخاص بـ Tokio.



إنشاء دوال غير متزامنة والعمل مع المهام



يمكنك إنشاء دوال غير متزامنة خاصة بك باستخدام الكلمة المفتاحية async fn:



use std::time::Duration;use tokio::time::sleep;

async fn simulate_work(id: u32, duration_secs: u64) -> String { println!("بدأت المهمة {}", id); sleep(Duration::from_secs(duration_secs)).await; // تأخير غير متزامن println!("اكتملت المهمة {}", id); format!("نتيجة المهمة {}", id)}

#[tokio::main]async fn main() { let start = std::time::Instant::now(); // إنشاء مهام غير متزامنة (tasks) let task1 = tokio::spawn(simulate_work(1, 2)); let task2 = tokio::spawn(simulate_work(2, 1)); let task3 = tokio::spawn(simulate_work(3, 3)); // انتظار اكتمال جميع المهام let results = tokio::join!(task1, task2, task3); // معالجة النتائج for result in &results { match result { Ok(msg) => println!("{}", msg), Err(e) => eprintln!("خطأ: {}", e), } } println!("الوقت الإجمالي: {:?}", start.elapsed()); // سيتم التنفيذ في حوالي 3 ثوانٍ، وليس 6!}


الدالة tokio::spawn تنشئ مهمة غير متزامنة مستقلة، يتم تنفيذها بالتوازي مع المهام الأخرى. tokio::join! ينتظر اكتمال جميع الـ futures الممررة إليه.



تقنيات متقدمة

المدونات

توصيات الكتب