سؤال

لدي بعض رمز نقل الملفات عالي الأداء الذي كتبته في C# باستخدام INSYNC Programming Model (APM) (على سبيل المثال ، BeginRead/EndRead). يقرأ هذا الرمز ملفًا من قرص محلي ويكتبه إلى مأخذ.

للحصول على أفضل أداء على الأجهزة الحديثة ، من المهم الاحتفاظ بأكثر من عملية I/O متميزة أثناء الرحلة كلما كان ذلك ممكنًا. وهكذا ، أنشر عدة BeginRead العمليات على الملف ، ثم عند اكتمال المرء ، أدعو أ BeginSend على المقبس ، وعندما يكمل ذلك أفعل آخر BeginRead على الملف. التفاصيل أكثر تعقيدًا قليلاً من ذلك ولكن على المستوى العالي هذه هي الفكرة.

لقد عملت الكود المستند إلى APM ، لكن من الصعب جدًا متابعته وربما يكون لديه أخطاء تزامنة خفية. أحب استخدام TPL لهذا بدلاً من ذلك. توقعت ذلك Task.Factory.FromAsync سوف تفعل ذلك فقط ، ولكن هناك صيد.

جميع عينات الإدخال/الإخراج التي رأيتها (خاصة StreamExtensions فئة في إضافات الامتدادات الموازية) افترض قراءة واحدة تليها كتابة واحدة. هذا لن يؤدي الطريقة التي أحتاجها.

لا يمكنني استخدام شيء بسيط مثل Parallel.ForEach أو تمديد الإضافات Task.Factory.Iterate نظرًا لأن مهام I/O Async لا تقضي الكثير من الوقت على موضوع العمال ، فإن التوازي يبدأ مهمة أخرى ، مما يؤدي إلى العشرات أو المئات من عمليات الإدخال/الإخراج المعلقة ؛ اكثر من اللازم! يمكنك العمل حول ذلك بواسطة Waitعلى مهامك ، ولكن هذا يسبب إنشاء مقبض حدث (كائن kernel) ، وانتظار حظر في مقبض انتظار المهمة ، الذي يربط سلسلة من العمال. يتجنب تطبيقي المستند إلى APM كلا هذين الأشياء.

لقد كنت ألعب بطرق مختلفة للحفاظ على عمليات القراءة/الكتابة المتعددة أثناء الرحلة ، وتمكنت TPL الاصطلاحية.

هل تصارع أي شخص آخر مع مشكلة مثل هذه مع TPL؟ أي اقتراحات؟

هل كانت مفيدة؟

المحلول

إذا كنت قلقًا بشأن الكثير من المواضيع ، فيمكنك فقط ضبط ParallelOptions.MaxDegreeOfParallelism إلى رقم مقبول في مكالمتك إلى Parallel.ForEach.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top