دعم التقارير المرحلية والنتائج المتزايدة في .NET 4.0 "مكتبة المهام الموازية"

StackOverflow https://stackoverflow.com/questions/1535749

سؤال

وأنا أعلم ذلك مكتبة المهام الموازية لا يزال في مرحلة تجريبية ومن المحتمل أن يكون هناك موارد أقل متاحة ولكن من كل ما قرأته، تمنح المكتبة معاملة خاصة جدًا له جدولة المهام, معالجة الاستثناء و إلغاء.

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

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

المحلول

يقوم هذا المثال بتحديث شريط التقدم:

using System;   
using System.Threading;   
using System.Threading.Tasks;   
using System.Windows.Forms;   

class SimpleProgressBar : Form   
{   
    [STAThread]   
    static void Main(string[] args)   
    {   
        Application.EnableVisualStyles();   
        Application.Run(new SimpleProgressBar());   
    }   

    protected override void OnLoad(EventArgs e)   
    {   
        base.OnLoad(e);   

        int iterations = 100;   

        ProgressBar pb = new ProgressBar();   
        pb.Maximum = iterations;   
        pb.Dock = DockStyle.Fill;   
        Controls.Add(pb);   

        Task.ContinueWith(delegate   
        {   
            Parallel.For(0, iterations, i =>  
            {   
                Thread.SpinWait(50000000); // do work here   
                BeginInvoke((Action)delegate { pb.Value++; });   
            });   
        });   
    }   
}  

تحديث شريط التقدم من داخل Parallel.For

نصائح أخرى

هذه واحدة من أفضل نتائج البحث الخاصة بي ولا يوجد حتى الآن مثال للتقدم فيها Task Parallel Library هنا...

لقد صادفت اليوم TPL لأنني أرغب في تطوير تطبيق جديد متعدد الخيوط ولكن بدون استخدام BackgroundWorker (لأنني قرأت في مكان ما عن المهمة باستخدام رمز جميل من قبل)

أقوم بتجميع المثال من إجابة @Stephen Cleary، والرابط الخاص به معقد للغاية للبحث عن التقدم، وبعض مواقع الويب الأخرى.

هذا هو المثال البسيط للغاية لكيفية القيام بذلك تقدم و مكتمل مع طريقة آمنة لموضوع واجهة المستخدم:

        TaskScheduler currentTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
        Task<string>.Factory.StartNew(() =>
        {
            // loop for about 10s with 10ms step
            for (int i = 0; i < 1000; i++)
            {
                Thread.Sleep(10);
                Task.Factory.StartNew(() =>
                {
                    // this is a task created each time you want to update to the UI thread.
                    this.Text = i.ToString();
                }, CancellationToken.None, TaskCreationOptions.None, currentTaskScheduler);
            }
            return "Finished!";
        })
        .ContinueWith(t =>
        {
            // this is a new task will be run after the main task complete!
            this.Text += " " + t.Result;
        }, currentTaskScheduler);

سيتم عرض الرمز من 1 إلى 1000 في 10s ثم إلحاق "الانتهاء!" سلسلة في شريط عنوان نموذج Windows.يمكنك أن ترى أن TaskScheduler هي الطريقة الصعبة لإنشاء تحديث آمن لمؤشر ترابط واجهة المستخدم لأنني أعتقد أن المهمة المجدولة للتشغيل على مؤشر الترابط الرئيسي.

لا يوجد دعم مدمج لهذا مثل ما يقدمه برنامج BackgroundWorker.

يمكنك استخدام SynchronizationContext مباشرة؛هناك فيديو ممتاز هنا: http://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video=TasksAndThreadAffinity.wmv

يقوم المؤلف بتطوير حلين في هذا الفيديو:أحدهما يستخدم SynchronizationContext والآخر يستخدم استمرارية المهام.بالنسبة لمشكلتك، لن تعمل الاستمرارات، لكن نهج SynchronizationContext سيعمل بشكل جيد.

ملاحظة.إذا كنت تقوم بإنشاء تعليمات برمجية قابلة لإعادة الاستخدام، فعند التقاط SynchronizationContext.Current، يجب عليك اختبار القيمة الخالية و(إذا كانت فارغة) استخدام SynchronizationContext المنشأ افتراضيًا بدلاً من ذلك.

تحديث:لقد قمت بنشر رمز لهذا على مدونتي.الحل الخاص بي يعتمد في الواقع على أ Task الذي تمت جدولته مرة أخرى إلى مؤشر ترابط واجهة المستخدم بواسطة a TaskScheduler الذي يستخدم SynchronizationContext تحته.على عكس الإجابة المقبولة، سيعمل هذا الحل مع كل من WPF وWindows Forms.

TPL ليس موجهًا بشكل خاص نحو دعم واجهة المستخدم، ويمكنك (لا يزال) استخدام BackgroundWorker لذلك.أما بالنسبة لإرسال أو معالجة النتائج المتوسطة، فهناك فئات تجميعية جديدة (ConcurrentQueue) لدعم ذلك.

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

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