كيفية معالجة العناصر في قائمة الانتظار بشكل تسلسلي على مؤشر ترابط أولوية منخفضة باستخدام ملحقات متوازية
-
27-09-2019 - |
سؤال
أريد أن أعرف ما هي أفضل طريقة لمعالجة نتائج عملية طويلة المدى بشكل تسلسلي ولكن على خيط منخفضة الأذرع باستخدام .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). يمكن أن يحد جدولة المهمة المخصصة الخاصة بك من التزامن مع واحد في وقت واحد وفرض تنفيذ صارم داخل الطلب.
يتيح لك إنشاء جدولة المهام أيضًا التحكم في أولوية مؤشر الترابط ، أو الشقة التي قد تكون مرغوبة في بعض الحالات.
أنت تصف حرفيًا حالة الاستخدام لمؤسسة سير العمل - إنها تفعل كل هذه الأشياء من أجلك :)