كيفية معالجة العناصر في قائمة الانتظار بشكل تسلسلي على مؤشر ترابط أولوية منخفضة باستخدام ملحقات متوازية

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

سؤال

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

لدي الفئة التالية التي تقوم بالتنفيذ وتوفر النتائج:

public class Step 
{
  public string Name { get; set; }
  public TimeSpan Duration { get; set; }
  public bool Completed { get; set; }

  public void Execute() 
  {
     DateTime before = DateTime.Now;
     RemotedService.DoSomeStuff();
     Duration = DateTime.Now - before;
     Completed = true;
  }
}

كيف يمكنني معالجة هذه الخطوات وأيضًا حفظها في ملف ، بالترتيب ، بعد معالجتها؟ أود حفظهم في ملف RemotedService.DoSomeStuff() ينتظر استجابة من الخادم.

ستكون الكتابة إلى الملف هكذا:

using (StreamWriter w = File.AppendText("myFile.txt"))
{
  var completedStep = completedSteps.Dequeue();
  w.WriteLine(string.Format("Completed {0} with result: {1} and duration {2}", 
                            completedStep.Name, 
                            completedStep.Completed, 
                            completedStep.Duration));
}

خيار واحد يتبادر إلى الذهن هو إضافتها إلى Queue ولديها Timer هذا يعالجهم. ولكن هذا لا يستفيد من توقف المكالمات عن بُعد.

خيار آخر يتبادر إلى الذهن هو كتابة كل نتيجة بشكل غير متزامن إلى الملف باستخدام أ System.Threading.Tasks.Task لكل Step, ، لكن هذا لا يضمن أن يتم حفظهم بالترتيب وقد يقدم أيضًا الخلاف مع الكتابة إلى الملف.

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

المحلول

أود أن أقترح إنشاء ملف BlockingCollection<Step> (نرى System.Collections.Concurrent مساحة الاسم). مع اكتمال كل خطوة ، تتم إضافتها إلى تلك المجموعة. السلوك الافتراضي لـ BlockingCollection هو العمل كطابور ، لذلك ستحصل على سلوك FIFO الذي تبحث عنه.

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

لذا ، إذا أضفت قائمة الانتظار:

static private BlockingCollection<Step> LogQueue = new BlockingCollection<Step>();

سوف تضيف هذا إلى الخاص بك Execute الطريقة ، بعد اكتمال العنصر:

LogQueue.Add(this);

وخيط التسجيل الخاص بك ، والذي ستبدأ في المُنشئ الثابت:

static void LoggingThread()
{
    using (var w = new StreamWriter(...))
    {
        while (!LogQueue.IsCompleted())
        {
            Step item;
            if (LogQueue.TryTake(out item))
            {
                w.WriteLine(....);
            }
        }
    }
}

مؤشر ترابط التسجيل كما كتبت يستخدم أ System.Threading مسلك. قد يكون هناك طريقة أسهل أو أفضل للقيام بذلك مع TPL. أنا لست على دراية بعد TPL ، لذلك لم أستطع القول.

نصائح أخرى

نهج واحد هو إنشاء جدولة مهمة مخصصة (انظر http://msdn.microsoft.com/en-us/library/ee789351.aspx). يمكن أن يحد جدولة المهمة المخصصة الخاصة بك من التزامن مع واحد في وقت واحد وفرض تنفيذ صارم داخل الطلب.

يتيح لك إنشاء جدولة المهام أيضًا التحكم في أولوية مؤشر الترابط ، أو الشقة التي قد تكون مرغوبة في بعض الحالات.

أنت تصف حرفيًا حالة الاستخدام لمؤسسة سير العمل - إنها تفعل كل هذه الأشياء من أجلك :)

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