تنسيقات متينة

يستخدم التنسيق الدائم وظيفة التنسيق لتنسيق تنفيذ وظائف أخرى في سير عمل موثوق وطويل الأمد يعرف بالكامل بالشيفرة. تتميز وظائف المنسق بالخصائص التالية:

  • هم يحددون سير العمل باستخدام الكود الإجرائي. ليست هناك حاجة إلى مخططات أو مصممين تصريحيين.
  • يستدعي دوال أخرى بشكل متزامن وغير متزامن. يمكنك حفظ المخرجات من الدوال المستدعاة إلى المتغيرات المحلية.
  • تقوم تلقائيا بنقطة التحقق من تقدم التنفيذ عندما تستدعي await الدالة عامل أو (or yield )، حتى لا تفقد العملية الحالة المحلية عند إعادة التدوير أو إعادة تشغيل الجهاز الافتراضي.
  • تدعم العمليات طويلة الأمد. العمر الافتراضي الكلي لمثيل الأوركسترا قد يكون ثوان أو أيام أو شهور، أو يمكنك ضبط النسخة لتصبح لا تنتهي أبدا.

تقدم هذه المقالة نظرة عامة على التنسيقات الموسيقية الدائمة، بما في ذلك هوية التوزيع الأوركسترالي، مصادر الأحداث، تاريخ التنفيذ، وأنماط سير العمل الشائعة مثل التنسيقات الفرعية، المؤقتات الدائمة، والتعامل مع الأخطاء.

مهم

سينتهي الدعم للنموذج قيد التنفيذ في 10 نوفمبر 2026. نوصي بشدة بترحيل تطبيقاتك إلى نموذج العامل المعزول للحصول على الدعم الكامل.

للحصول على معلومات حول أنواع الوظائف المتاحة في تطبيق Durable Functions، راجع نموذج برمجة المهام المتطورة.

نصيحة

إذا استخدمت C# مع نموذج العامل المعزل .NET، يمكنك كتابة التنسيقات باستخدام نهج قائم على الدوال (طرق ثابتة مع [Function] خصائص) أو نهج قائم على الفئة (الفئات التي ترث من TaskOrchestrator<TInput, TOutput>). يتطلب النهج القائم على الفئة حزمة مولد المصدر Microsoft.DurableTask.Generators ويوفر استدعاءات ذات نوع قوي. لمزيد من المعلومات، راجع مولدات المصدر وصياغة الجملة القائمة على الفئة. أمثلة كود C# في هذا المقال تظهر كلا النهجين.

توفر مجموعات تطوير المهام المتواصلة نفس قدرات التنسيق التي توفر وظائف دائمة لبناء سير عمل موثوق وطويل الأمد مع معالجة متوازية وتنسيق مدفوع بالأحداث. على عكس الوظائف المتينة، تعمل تنسيقات SDK للمهام الدائمة كتطبيقات مستقلة مدعومة بجدولة المهام الدائمة.

هوية التنسيق

كل نسخة من التنسيق لها معرف مثيل، يعرف أيضا بمعرف الحالة. افتراضيا، كل معرف حالة هو معرف فريد عالمي مولد تلقائيا (GUID). ومع ذلك، يمكنك استخدام أي قيمة نصية ينشئها المستخدم كمعرف مثيل. يجب أن يكون كل معرف مثيل التزامن فريدا داخل مركز المهام.

تنطبق القواعد التالية على معرفات الممثلات:

  • يجب أن يكون العدد بين 1 و100 حرف.
  • يجب ألا تبدأ ب @.
  • يجب ألا تحتوي /على ، \، #، أو ? الحروف.
  • يجب ألا تحتوي على شخصيات تحكم.

ملحوظة

استخدم معرفات المثيلات المولدة تلقائيا كلما أمكن. استخدم معرفات المثيل التي ينشها المستخدم في السيناريوهات التي يكون فيها ربط واحد لواحد بين مثيل تنسيق وكيان خارجي خاص بالتطبيق، مثل أمر شراء أو مستند.

ملحوظة

يمكن أن يختلف تطبيق قواعد تقييد الحروف حسب مزود التخزين الذي يستخدمه التطبيق. للمساعدة في ضمان السلوك الصحيح والتوافق، اتبع قواعد معرف المثيل السابقة.

معرف مثيل التنسيق هو معلمة مطلوبة لمعظم عمليات إدارة المثيلات. معرفات العينات مهمة أيضا للتشخيص. على سبيل المثال، تستخدمها عند البحث في بيانات تتبع التنسيق في Application Insights لأغراض استكشاف الأخطاء أو التحليلات. لهذا السبب، حفظ معرفات المثيلات المولدة في موقع خارجي يسهل الرجوع إليها لاحقا، مثل سجلات قاعدة البيانات أو التطبيقات.

معرف مثيل التنسيق هو معلمة مطلوبة لمعظم عمليات إدارة المثيلات. معرفات المثيلات مهمة أيضا للتشخيص، لذا حفظ معرفات المثيلات المولدة في موقع خارجي يسهل الرجوع إليها لاحقا، مثل قاعدة بيانات أو سجلات التطبيقات.

الموثوقيه

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

يستخدم إطار عمل المهام الدائمة مصدر الأحداث بشكل شفاف. خلف الكواليس، تستخدم وظيفة التنسيق عامل await في C# وعامل yield في JavaScript و Python. هذه المشغلات تعود إلى موزع إطار المهام الدائم التحكم في خيط الأوركستراتور. في Java، يؤدي استدعاء .await() في مهمة إلى إعادة التحكم إلى المرسل عبر نسخة مخصصة من Throwable. ثم يقوم الموزع بإرسال أي إجراءات جديدة يقوم المنظم بجدولة الوظيفة إلى التخزين. تشمل أمثلة الإجراءات استدعاء وظيفة أو أكثر من الوظائف الفرعية أو جدولة مؤقت دائم. يقوم إجراء الالتزام الشفاف بتحديث تاريخ تنفيذ نسخة التنسيق عن طريق إضافة جميع الأحداث الجديدة إلى التخزين، تماما مثل سجل الإلحاق فقط. وبالمثل، يقوم إجراء الالتزام بإنشاء رسائل في التخزين لجدولة العمل الفعلي. في هذه المرحلة ، يمكن تفريغ وظيفة المنسق من الذاكرة.

يمكنك استخدام أي من مزودي التخزين المتاحين كمخزن حالة تشغيل.

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

ملحوظة

لكي يعمل نمط إعادة التشغيل بشكل صحيح وموثوق، يجب أن يكون كود وظيفة التنسيق حتميا. يمكن أن يؤدي كود التنسيق غير الحتمي إلى أخطاء في وقت التشغيل أو سلوك غير متوقع آخر. لمزيد من المعلومات حول قيود الكود لوظائف الأوركستراتور، راجع قيود كود وظائف المنسق.

ملحوظة

إذا كانت وظيفة المنسق ترسل رسائل سجل، فقد يؤدي سلوك إعادة التشغيل إلى إصدار رسائل سجل مكررة. لمعرفة سبب حدوث هذا السلوك وكيفية التعامل معه، راجع تسجيل إعادة التشغيل الآمن.

تاريخ التنسيق

يقترن سلوك تحديد مصادر الأحداث لإطار عمل المهام الدائم ارتباطا وثيقا برمز دالة المنسق الذي تكتبه. افترض أن لديك وظيفة منسق لسلسلة النشاط، كما هو الحال في المثال التالي.

نموذج العامل المعزول
[Function("HelloCities")]
public static async Task<List<string>> Run(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var outputs = new List<string>();

    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

    // Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
    return outputs;
}

نموذج قائم على الطبقة (عامل معزول)

يستخدم النهج القائم على الفئة مولد المصدر ويتطلب حزمة NuGet من Microsoft.DurableTask.Generators .

using Microsoft.DurableTask;

[DurableTask]
public class HelloCities : TaskOrchestrator<object?, List<string>>
{
    public override async Task<List<string>> RunAsync(
        TaskOrchestrationContext context, object? input)
    {
        var outputs = new List<string>();

        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

        // Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
        return outputs;
    }
}

النموذج أثناء العملية
[FunctionName("HelloCities")]
public static async Task<List<string>> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var outputs = new List<string>();

    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

    // Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
    return outputs;
}
using Microsoft.DurableTask;

[DurableTask]
public class HelloCities : TaskOrchestrator<object?, List<string>>
{
    public override async Task<List<string>> RunAsync(TaskOrchestrationContext context, object? input)
    {
        var outputs = new List<string>();

        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

        return outputs;
    }
}

عندما تقوم بجدولة دالة نشاط، يحفظ إطار عمل المهام الدائم حالة تنفيذ الدالة عند نقاط التحقق المختلفة. في كل نقطة تفتيش، يحفظ الإطار الحالة في خلفية تخزين متينة. هذه الحالة هي تاريخ الأوركسترا.

جدول المحفوظات

في كل نقطة تفتيش، يقوم إطار العمل الدائم بالإجراءات التالية:

  • تحفظ سجل التنفيذ إلى التخزين الدائم.
  • يقوم بإدراج الرسائل في قائمة الانتظار للوظائف التي يريد المنسق استدعاءها.
  • يقوم بإدخال رسائل لجهاز التنسيق نفسه، مثل رسائل المؤقت الدائم.

عندما ينتهي نقطة التحقق، يقوم الإطار بإزالة وظيفة التنسيق من الذاكرة حتى يبقى هناك المزيد من العمل للقيام به.

ملحوظة

لا يوفر تخزين Azure أي ضمانات معاملية حول اتساق البيانات بين تخزين الجداول وقوائم الانتظار عند حفظ البيانات. للتعامل مع الإخفاقات، يستخدم مزود Durable Functions تخزين Azureأنماط الاتساق النهائية، مثل فصل مسؤولية الأوامر والاستعلام (CQRS). تقدم شركات التخزين البديلة ضمانات أقوى للاتساق:

عندما تنتهي الدالة المعروضة سابقا، يبدو تاريخها مشابها للبيانات في الجدول التالي في تخزين الجدول. تم اختصار الإدخالات للتوضيح.

مفتاح التقسيم (InstanceId) نوع الحدث طابع زمني الإدخال الاسم النتيجة Status
EAE885B التنفيذبدأ 2021-05-05T18:45:28.852Z قيمة فارغة HelloCities
EAE885B المنسقبدأ 2021-05-05T18:45:32.362Z
EAE885B المهام المجدولة 2021-05-05T18:45:32.670Z قل مرحبا
EAE885B المنسقتم 2021-05-05T18:45:32.670Z
EAE885B المهمة المنجزة 2021-05-05T18:45:34.201Z """مرحبا طوكيو!"
EAE885B المنسقبدأ 2021-05-05T18:45:34.232Z
EAE885B المهام المجدولة 2021-05-05T18:45:34.435Z قل مرحبا
EAE885B المنسقتم 2021-05-05T18:45:34.435Z
EAE885B المهمة المنجزة 2021-05-05T18:45:34.763Z """مرحبا سياتل!"
EAE885B المنسقبدأ 2021-05-05T18:45:34.857Z
EAE885B المهام المجدولة 2021-05-05T18:45:34.857Z قل مرحبا
EAE885B المنسقتم 2021-05-05T18:45:34.857Z
EAE885B المهمة المنجزة 2021-05-05T18:45:34.919Z """مرحبا لندن!"
EAE885B المنسقبدأ 2021-05-05T18:45:35.032Z
EAE885B المنسقتم 2021-05-05T18:45:35.044Z
EAE885B التنفيذمكتمل 2021-05-05T18:45:35.044Z "[""مرحبا طوكيو!"",""مرحبا سياتل!","""مرحبا لندن!""]" اكتمل

تحتوي أعمدة الجداول على القيم التالية:

  • PartitionKey: معرف مثيل التوزيع الموسيقي.
  • نوع الحدث: نوع الحدث. للحصول على أوصاف تفصيلية لجميع أنواع الأحداث التاريخية، انظر Durable Task Framework History Events.
  • الطابع الزمني: الطابع الزمني العالمي المنسق للحدث التاريخي.
  • الإدخال: الإدخال بتنسيق JSON للوظيفة.
  • الاسم: اسم الدالة المستدعية.
  • النتيجة: مخرج الدالة، وتحديدا قيمة العائد الخاصة بها.

التحذير

هذا الجدول مفيد كأداة تصحيح الأخطاء، لكن قد يتغير تنسيقه ومحتواه مع تطور امتداد Durable Functions.

في كل مرة تستأنف فيها الوظيفة بعد انتظار إكمال مهمة، يعيد إطار العمل الدائم تشغيل وظيفة المنسق من الصفر. في كل إعادة تشغيل، يستشاور سجل التنفيذ لتحديد ما إذا كانت المهمة غير المتزامنة الحالية مكتملة. إذا أظهر سجل التنفيذ أن المهمة قد اكتملت بالفعل، يعيد الإطار تشغيل مخرجات تلك المهمة وينتقل إلى المهمة التالية. تستمر هذه العملية حتى يتم إعادة تشغيل تاريخ الإعدام بالكامل. بعد إعادة تشغيل سجل التنفيذ الحالي، تعاد المتغيرات المحلية إلى قيمها السابقة.

الميزات والأنماط

تصف الأقسام التالية ميزات وأنماط وظائف الموزع.

التوزيع الفرعي في وظائف الموزع

يمكن لوظائف المنسق استدعاء دوال النشاط، لكنها يمكنها أيضا استدعاء دوال منسق أخرى. على سبيل المثال، يمكنك إنشاء تنسيق أكبر من مكتبة وظائف المنسق. أو يمكنك تشغيل مثيلات متعددة لدالة المنسق بالتوازي.

لمزيد من المعلومات وللحصول على أمثلة، انظر sub-orchestrations في Durable Functions (دالات Azure).

مؤقتات متينة

يمكن للأنظمة التنسيقية جدولة مؤقتات دائمة لتنفيذ التأخيرات أو لإعداد معالجة المهلة على الإجراءات غير المتزامنة. استخدم مؤقتات متينة في وظائف الأوركستراتور بدلا من واجهات برمجة التطبيقات الأصلية sleep للغة.

لمزيد من المعلومات وللحصول على أمثلة، راجع مؤقتات في Durable Functions (دالات Azure).

الأحداث الخارجية

يمكن أن تنتظر وظائف المنسق حتى تقوم الأحداث الخارجية بتحديث مثيل التزامن. ميزة Durable Functions هذه غالبا ما تكون مفيدة للتعامل مع التفاعلات البشرية أو الاستدعاءات الخارجية الأخرى.

لمزيد من المعلومات والأمثلة، راجع التعامل مع الأحداث الخارجية في Durable Functions (دالات Azure).

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

يمكن لوظائف المنسق استخدام ميزات معالجة الأخطاء في لغة البرمجة. يدعم كود التوزيع الموسيقي أنماطا موجودة مثل try/catch.

يمكن لوظائف المنسق أيضا إضافة نهج إعادة المحاولة إلى النشاط أو وظائف المنسق الفرعي التي تستدعيها. إذا فشل نشاط أو وظيفة منسق فرعي مع استثناء، يمكن لنهج إعادة المحاولة المحدد تأخير التنفيذ وإعادة محاولة التنفيذ تلقائيا حتى عدد محدد من المرات.

ملحوظة

إذا كان هناك استثناء غير معالج في وظيفة الموزع، ينتهي وضع التوزيع في حالة معينة Failed . لا يمكنك إعادة محاولة نسخة أوركستراسيين بعد فشلها.

لمزيد من المعلومات والأمثلة، راجع التعامل مع أخطاء في Durable Functions (دالات Azure).

الأقسام الحرجة (Durable Functions 2.x)

حالات التوزيع الموسيقي تكون ذات خيط واحد، لذا ظروف السباق ليست مصدر قلق داخل التوزيع الأوركسترالي. ومع ذلك ، فإن ظروف السباق ممكنة عندما تتفاعل التنسيقات مع الأنظمة الخارجية. لتخفيف ظروف السباق عند التفاعل مع الأنظمة الخارجية، يمكن لوظائف المنسق تحديد الأقسام الحرجة باستخدام قفل. تدعم .NET وJavaScript الأقسام الحرجة.

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

استخدم الطريقة LockAsync للدخول إلى القسم الحرج.

[FunctionName("Synchronize")]
public static async Task Synchronize(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var lockId = new EntityId("LockEntity", "MyLockIdentifier");
    using (await context.LockAsync(lockId))
    {
        // Critical section. Only one orchestration can enter at a time.
    }
}

في تنسيقات العمال المعزولة ب ..NET، استخدم TaskOrchestrationContext.Entities.LockEntitiesAsync (انظر تعيين واجهة برمجة التطبيقات المعزولة ب ..NET).

تقوم هذه الطريقة LockAsync بالحصول على الأقفال المتينة وتعيد إلى IDisposable النقطة التي تنهي القسم الحرج عند التخلص منها. يمكن استخدام هذه IDisposable النتيجة مع كتلة using للحصول على تمثيل نحوي للقسم الحرج. عندما تدخل دالة المنسق إلى قسم حرج، يمكن لمثيل واحد فقط تنفيذ كتلة التعليمات البرمجية هذه. أي حالات أخرى تحاول دخول القسم الحرج تحظر حتى يخرج المثيل السابق من القسم الحرج.

ميزة القسم الحرج مفيدة أيضا لتنسيق التغييرات على الكيانات الدائمة. لمزيد من المعلومات حول الأقسام الحرجة، راجع تنسيق الكيانات.

ملحوظة

الأقسام الحرجة متوفرة في Durable Functions 2.x لتنسيقات .NET وJavaScript. بالنسبة ل .NET، تختلف واجهة برمجة التطبيقات حسب النموذج: الاستخدامات IDurableOrchestrationContext.LockAsyncأثناء العملية، بينما تستخدم TaskOrchestrationContext.Entities.LockEntitiesAsyncمعزولة .

المكالمات إلى نقاط نهاية HTTP (Durable Functions 2.x)

لا يمكن لوظائف الأوركستراتور تنفيذ عمليات الإدخال/الإخراج، كما هو موضح في قيود كود وظائف الأوركستراتور. لتجاوز هذا القيد، قم بتغليف أي كود يحتاج لتنفيذ عمليات الإدخال/الإخراج في دالة نشاط. غالبا ما تستخدم التوزيعات التي تتفاعل مع الأنظمة الخارجية وظائف النشاط لإجراء استدعاءات HTTP وإعادة النتائج إلى التنسيق.

لتبسيط هذا النمط الشائع، يمكن لوظائف التنسيق استخدام الطريقة CallHttpAsync لاستدعاء واجهات برمجة تطبيقات HTTP مباشرة.

نموذج العامل المعزول
[Function("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    Uri url = context.GetInput<Uri>();

    // Make an HTTP GET request to the specified endpoint.
    DurableHttpResponse response = await context.CallHttpAsync(
        method: HttpMethod.Get,
        uri: url,
        content: null,
        retryOptions: null);

    if ((int)response.StatusCode == 400)
    {
        // Handle error codes.
    }
}

النموذج أثناء العملية
[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Uri url = context.GetInput<Uri>();

    // Make an HTTP GET request to the specified endpoint.
    DurableHttpResponse response = 
        await context.CallHttpAsync(HttpMethod.Get, url);

    if ((int)response.StatusCode == 400)
    {
        // Handle error codes.
    }
}

بالإضافة إلى دعم أنماط الطلبات والرد الأساسية، تدعم الطريقة التعامل التلقائي مع أنماط استطلاع HTTP 202 غير المتزامنة الشائعة. كما يدعم المصادقة مع الخدمات الخارجية باستخدام الهويات المدارة.

لمزيد من المعلومات وأمثلة مفصلة، راجع ميزات HTTP.

ملحوظة

استدعاء نقاط نهاية HTTP مباشرة من وظائف التنسيق متوفر في Durable Functions 2.0 وما بعده.

تمرير عدة معلمات إلى دوال النشاط

لا يمكنك تمرير عدة معلمات مباشرة إلى دالة نشاط. مرر مصفوفة من الكائنات أو الكائنات المركبة بدلا من ذلك.

نموذج العامل المعزول

في .NET، استخدم نوع مركب قابل للتسلسل، مثل سجل، لتمرير عدة معلمات.

public record CourseInfo(string Major, int UniversityYear);

[Function("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    int universityYear = context.GetInput<int>();
    CourseInfo courseInfo = new("ComputerScience", universityYear);
    object courseRecommendations = await context.CallActivityAsync<object>(
        "CourseRecommendations", courseInfo);
    return courseRecommendations;
}

النموذج أثناء العملية

في .NET، استخدم نوع مركب قابل للتسلسل لتمرير عدة معلمات. العينة التالية تستخدم فئة بسيطة:

public class CourseInfo
{
    public string Major { get; set; }
    public int UniversityYear { get; set; }
}

[FunctionName("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var input = new CourseInfo
    {
        Major = "ComputerScience",
        UniversityYear = context.GetInput<int>()
    };

    object courseRecommendations = await context.CallActivityAsync<object>(
        "CourseRecommendations",
        input);
    return courseRecommendations;
}

في .NET، استخدم أنواع السجلات أو المجموعات لتمرير عدة معلمات ككائن مركب واحد.

using Microsoft.DurableTask;

public record LocationInfo(string City, string State);

[DurableTask]
public class GetWeatherOrchestration : TaskOrchestrator<object?, string>
{
    public override async Task<string> RunAsync(TaskOrchestrationContext context, object? input)
    {
        var location = new LocationInfo("Seattle", "WA");
        string weather = await context.CallActivityAsync<string>("GetWeather", location);
        return weather;
    }
}

الخطوات التالية