C# Async - كيف تعمل؟
-
27-09-2019 - |
سؤال
أعلنت Microsoft Visual Studio Async CTP اليوم (28 أكتوبر 2010) الذي يقدم async
و await
الكلمات الرئيسية في C#/VB لتنفيذ الطريقة غير المتزامنة.
أولاً ، اعتقدت أن المترجم يترجم الكلمات الرئيسية إلى إنشاء مؤشر ترابط ولكن وفقًا لـ ورق ابيض و Anders Hejlsberg's عرض PDC (في الساعة 31:00) تحدث العملية غير المتزامنة تمامًا على الخيط الرئيسي.
كيف يمكنني تنفيذ عملية بالتوازي مع نفس الخيط؟ كيف يمكن ذلك من الناحية الفنية وما هي الميزة المترجمة بالفعل في IL؟
المحلول
يعمل بشكل مشابه ل yield return
الكلمة الرئيسية في C# 2.0.
الطريقة غير المتزامنة ليست في الواقع طريقة متسلسلة عادية. يتم تجميعه في آلة الحالة (كائن) مع بعض الحالة (يتم تحويل المتغيرات المحلية إلى حقول للكائن). كل كتلة من الكود بين استخدامين await
هي "خطوة" لآلة الحالة.
هذا يعني أنه عندما تبدأ الطريقة ، فإنها تدير الخطوة الأولى فقط ، ثم تقوم جهاز الحالة بإرجاع بعض الأعمال التي يتعين القيام بها - عند الانتهاء من العمل ، سيتم تشغيل الخطوة التالية من آلة الحالة. على سبيل المثال هذا الرمز:
async Task Demo() {
var v1 = foo();
var v2 = await bar();
more(v1, v2);
}
سوف تترجم إلى شيء مثل:
class _Demo {
int _v1, _v2;
int _state = 0;
Task<int> _await1;
public void Step() {
switch(this._state) {
case 0:
this._v1 = foo();
this._await1 = bar();
// When the async operation completes, it will call this method
this._state = 1;
op.SetContinuation(Step);
case 1:
this._v2 = this._await1.Result; // Get the result of the operation
more(this._v1, this._v2);
}
}
الجزء المهم هو أنه يستخدم فقط SetContinuation
طريقة لتحديد أنه عند اكتمال العملية ، يجب أن تستدعي Step
الطريقة مرة أخرى (والطريقة تعرف أنه يجب تشغيل الجزء الثاني من الكود الأصلي باستخدام _state
مجال). يمكنك بسهولة أن تتخيل أن SetContinuation
سيكون شيئًا مثل btn.Click += Step
, ، والتي من شأنها أن تعمل تماما على موضوع واحد.
نموذج البرمجة غير المتزامن في C# قريب جدًا من مهام سير العمل غير المتزامنة (في الواقع ، إنه نفس الشيء ، بصرف النظر عن بعض التفاصيل الفنية) ، وكتابة تطبيقات واجهة المستخدم الرسومية الواحدة المتفاعلة باستخدام async
هو منطقة مثيرة للاهتمام - على الأقل أعتقد ذلك - انظر على سبيل المثال هذه المقالة (ربما يجب أن أكتب نسخة C# الآن :-)).
الترجمة مشابهة للتكرار (و yield return
) وفي الواقع ، كان من الممكن استخدام المتكررين لتنفيذ البرمجة غير المتزامنة في C# في وقت سابق. كتبت مقال عن ذلك منذ فترة - وأعتقد أنه لا يزال بإمكانك إعطائك بعض البصيرة حول كيفية عمل الترجمة.
نصائح أخرى
كيف يمكنني تنفيذ عملية بالتوازي مع نفس الخيط؟
لا يمكنك. عدم التزامن ليس "التوازي" أو "التزامن". قد يتم تنفيذ عدم التزامن بالتوازي ، أو قد لا يكون كذلك. قد يتم تنفيذه عن طريق تقسيم العمل إلى أجزاء صغيرة ، ووضع كل جزء من العمل في قائمة انتظار ، ثم تنفيذ كل جزء من العمل كلما صادف عدم القيام بأي شيء آخر.
لدي سلسلة كاملة من المقالات على مدونتي حول كيفية عمل كل هذه الأشياء ؛ من المحتمل أن يرتفع الشخص الذي يدور مباشرة في هذا السؤال يوم الخميس من الأسبوع المقبل. راقب
http://blogs.msdn.com/b/ericlippert/archive/tags/async/
للتفاصيل.
كما أفهمها ، ماذا async
و await
الكلمات الرئيسية تفعل أنه في كل مرة async
الطريقة توظف await
الكلمة الرئيسية ، سوف يحول المترجم باقي الطريقة إلى استمرار يتم جدولة عند اكتمال عملية ASYNC. ذلك يسمح async
طرق العودة إلى المتصل على الفور واستئناف العمل عند الانتهاء من جزء Async.
وفقًا للأوراق المتاحة ، هناك الكثير من التفاصيل ، لكن ما لم أكن مخطئًا ، فهذه هي جوهرها.
كما أراها ، فإن الغرض من أساليب Async هو عدم تشغيل الكثير من التعليمات البرمجية بالتوازي ، ولكن لتقطيع طرق Async إلى عدد من القطع الصغيرة ، والتي يمكن استدعاؤها حسب الحاجة. النقطة الأساسية هي أن المترجم سيتعامل مع جميع الأسلاك المعقدة للاسترداد باستخدام المهام/الاستمرارية. هذا لا يقلل من التعقيد فحسب ، بل يسمح بكتابة طريقة Async إلى حد ما مثل التعليمات البرمجية التقليدية المتزامنة.