متن خبر

نحوه عملکرد برنامه نویسی ناهمزمان در Rust – Futures و Async/Await با مثال هایی توضیح داده شده است

نحوه عملکرد برنامه نویسی ناهمزمان در Rust – Futures و Async/Await با مثال هایی توضیح داده شده است

شناسهٔ خبر: 698074 -




اگر با زبان هایی مانند جاوا اسکریپت و پایتون آشنایی دارید، ممکن است در مورد برنامه نویسی ناهمزمان شنیده باشید. و شاید شما تعجب کنید که چگونه در Rust کار می کند.

در این مقاله، یک نمای کلی ساده از نحوه عملکرد برنامه نویسی ناهمزمان در Rust به شما ارائه می دهم. در مورد معاملات آتی و همچنین async / .await خواهید آموخت.

این مقاله یک راهنمای مبتدی برای Rust یا برنامه نویسی ناهمزمان نیست، پس برای استفاده حداکثری از این راهنما باید کمی تجربه در برنامه نویسی در Rust و آشنایی با برنامه نویسی ناهمزمان داشته باشید.

با این گفته، بیایید شروع کنیم!

چه زمانی باید از برنامه نویسی ناهمزمان استفاده کرد؟

وظایف ناهمزمان مانند یک نسخه یکپارچه تر از رشته ها کار می کنند. شما می توانید آنها را در بسیاری از سناریوهای مشابه که می توانید از چندین رشته استفاده کنید استفاده کنید. مزایایی که برنامه‌نویسی همگام در چندین رشته ارائه می‌کند این است که برنامه‌های چند رشته‌ای در مقایسه با برنامه‌های ناهمزمان، سربار بیشتری برای کار روی چندین کار دارند.

اما این برنامه های ناهمزمان را بهتر از برنامه های چند رشته ای نمی کند. برنامه های چند رشته ای می توانند چندین کار محاسباتی فشرده را به طور همزمان اجرا کنند - و چندین برابر سریعتر از زمانی که همه وظایف را در یک رشته اجرا می کنید.

با کدنویسی ناهمزمان، تلاش برای اجرای همزمان چندین برنامه محاسباتی فشرده بسیار کندتر از اجرای هر کار بر روی یک رشته واحد خواهد بود.

برنامه نویسی ناهمزمان برای ساخت برنامه هایی که درخواست های شبکه زیادی می کنند یا بسیاری از عملیات IO مانند خواندن و نوشتن فایل بسیار خوب است.

من نمی توانم هر موردی را که می خواهید از تکنیک های ناهمزمان استفاده کنید، پوشش دهم. اما می توانم بگویم که برای کارهایی که زمان بیکاری زیادی دارند (مثلاً منتظر ماندن سرور برای پاسخ به درخواست شبکه) سودمندتر است.

در طول زمان بیکاری یک کار ناهمزمان، به جای مسدود کردن رشته، کنترل کننده رویداد روی سایر وظایف برنامه کار می کند تا زمانی که کار ناهمزمان برای پیشرفت آماده شود.

تحلیل اجمالی زنگ ناهمزمان - آینده

اصول اولیه Rust ناهمزمان Futures هستند. معاملات آتی شبیه به وعده های جاوا اسکریپت است. آنها روشی هستند که Rust می گوید: "هی، من بعداً نتیجه را به شما خواهم داد، اما فقط به این (نمونه آینده) ادامه دهید تا پیگیری کنید که آیا نتیجه آماده است یا خیر."

آینده ها صفاتی هستند، با حالت poll که یا Poll::Pending که نشان می دهد آینده در حال انجام وظیفه خود است، یا Poll::Ready نشان می دهد که آینده با وظیفه خود تمام شده است.

آینده ها تنبل هستند. آنها زمانی اجرا می شوند که شما آنها را .await (ما در بخش بعدی نحوه .await آنها را تحلیل خواهیم کرد). .await در آینده، اجرای یک رشته ناهمزمان را متوقف می کند و کار خود را شروع می کند. در این مرحله نتیجه روش poll Poll::Pending است. هنگامی که آینده با وظیفه خود تمام شد، وضعیت poll به Poll::Ready تبدیل می شود و آینده به رشته آن اجازه می دهد تا ادامه یابد.

اگر می‌خواهید بیشتر با جزئیات فنی درباره آتی آشنا شوید، می‌توانید مستندات را تحلیل کنید.

async/.wait در Rust

async و .await راه های اصلی کار با کدهای ناهمزمان در Rust هستند. async یک کلمه کلیدی برای اعلام توابع ناهمزمان است. در این توابع، کلمه کلیدی .await اجرای خود را تا زمانی که نتیجه آینده آماده شود متوقف می کند.

بیایید به یک مثال نگاه کنیم:

 async fn add (a: u8 , b: u8 ) -> u8 { a + b } async fn secondFunc () -> u8 { let a = 10 ; let b = 20 ; let result = add(a, b). await ; return result; }

هر تابع ناهمزمان اعلام شده با async fn مقدار بازگشتی خود را در آینده می‌پیچد. در خط سوم secondFunc ، ما .await آینده از add(a, b) هستیم تا قبل از بازگرداندن آن، نتیجه آن را بدست آوریم.

نحوه کار با عملیات ناهمزمان به صورت main

Rust به شما اجازه نمی دهد که عملکردهای اصلی async fn . اجرای عملیات ناهمزمان از یک تابع غیرهمزمان ممکن است منجر به عدم پایان کامل برخی از عملیات قبل از خروج از رشته اصلی شود.

در این بخش به دو راه حل این مشکل می پردازیم. دو راه برای انجام این کار با futures و tokio هستند. بیایید به هر دو نگاه کنیم.

tokio

tokio پلتفرمی است که ابزارها و APIها را برای اجرای برنامه های ناهمزمان ارائه می دهد. tokio همچنین به شما اجازه می دهد تا به راحتی یک تابع اصلی ناهمزمان را اعلام کنید، که به مشکلی که قبلا توضیح دادم کمک می کند.

برای نصب tokio در پروژه خود، این خط را به Cargo.toml آن اضافه کنید:

 [dependencies] tokio = { version = "1" , features = [ "full" ] }

پس از اضافه کردن خط، می توانید توابع main خود را به صورت زیر بنویسید:

 async fn add (a: u8 , b: u8 ) -> u8 { a + b } #[tokio::main] async fn main () { let a = 10 ; let b = 20 ; let result = add(a, b). await ; println! ( "{result}" ); }

کتابخانه futures

futures کتابخانه ای است که روش هایی را برای کار با Rust ناهمزمان ارائه می دهد. برای مورد استفاده ما، futures futures::executor::block_on() ارائه می دهد. این روش مشابه .await در توابع ناهمزمان عمل می کند. تا زمانی که نتیجه آینده آماده شود، نخ اصلی را مسدود می کند. futures::executor::block_on() نیز نتیجه آینده تکمیل شده را برمی گرداند.

برای نصب futures در پروژه خود، این خط را به Cargo.toml آن اضافه کنید:

 [dependencies] futures = "0.3"

پس از نصب کتابخانه، می توانید کاری شبیه به این انجام دهید:

 use futures::executor::block_on; async fn add (a: u8 , b: u8 ) -> u8 { a + b } fn main () { let a = 10 ; let b = 20 ; let result = block_on(add(a, b)); println! ( "{result}" ); }

ابتدا متد block_on را در خط اول وارد می کنیم و تا زمانی که نتیجه تابع add(a, b) آماده شود از متد برای مسدود کردن رشته اصلی استفاده می کنیم. ما همچنین مجبور نبودیم عملکرد main را مانند tokio ناهمزمان کنیم.

نتیجه گیری

برنامه نویسی ناهمزمان به شما امکان می دهد عملیات ها را به صورت موازی و با سربار و پیچیدگی کمتر در مقایسه با چند رشته ای سنتی اجرا کنید. در Rust به شما امکان می دهد برنامه های ورودی/خروجی و شبکه را کارآمدتر بسازید.

در حالی که این مقاله به شما کمک می کند تا با اصول برنامه نویسی ناهمزمان در Rust آشنا شوید، اما هنوز هم فقط یک نمای کلی است. مواردی وجود دارد که باید از ساختارهای دیگری مانند Pinning، Arcs و غیره در Rust استفاده کنید.

اگر سوال یا نظری دارید با من در میان بگذارید. با تشکر برای خواندن!

خبرکاو

ارسال نظر

دیدگاه‌ها بسته شده‌اند.


تبليغات ايهنا تبليغات ايهنا

تمامی حقوق مادی و معنوی این سایت متعلق به خبرکاو است و استفاده از مطالب با ذکر منبع بلامانع است