NET يعرّف وظيفة مؤشرات الترابط المتعددة في مساحة الاسم System.Threading. ولذلك، لاستخدام مؤشرات الترابط المتعددة، يجب عليك أولاً الإعلان عن مرجع لمساحة الاسم هذه (باستخدام System.Threading;).
أ. بدء سلسلة رسائل، كما يوحي الاسم، تعني عبارة "بدء سلسلة محادثات" إنشاء سلسلة رسائل وبدء تشغيلها، ويمكن للتعليمات البرمجية التالية تحقيق ذلك:
Thread thread1 = new Thread(new ThreadStart(Count));
حيث Count هي الوظيفة التي سيتم تنفيذها بواسطة الخيط الجديد.
ب. قتل الخيط
"قتل الخيط" هو القضاء على الخيط، حتى لا تضيع جهودك، من الأفضل تحديد ما إذا كان لا يزال على قيد الحياة (من خلال السمة IsAlive) قبل قتل الخيط، ثم استدعاء طريقة الإجهاض لقتل الخيط. .
ج. إيقاف الخيط مؤقتًا يعني ترك الخيط قيد التشغيل في وضع السكون لفترة من الوقت. على سبيل المثال، thread.Sleep(1000); هو السماح للخيط بالنوم لمدة ثانية واحدة.
د. الأولوية لا تحتاج إلى شرح. يتم استخدام سمة hreadPriority في فئة Thread لتعيين الأولوية، ولكن ليس هناك ما يضمن أن نظام التشغيل سيقبل الأولوية. يمكن تقسيم أولوية الخيط إلى 5 أنواع: عادي، فوق عادي، تحت عادي، أعلى، وأدنى. أمثلة التنفيذ المحددة هي كما يلي:
thread.Priority = ThreadPriority.Highest;
ه. تعليق الخيط
يتم استخدام أسلوب التعليق المرحلي لفئة مؤشر الترابط لتعليق مؤشر الترابط حتى يتم استدعاء الاستئناف قبل أن يتمكن مؤشر الترابط من الاستمرار في التنفيذ. إذا كان الخيط معلقًا بالفعل، فلن ينجح ذلك.
إذا (thread.ThreadState = ThreadState.Running)
{
Thread.Suspend();
}
f. يتم استخدام خيط الاسترداد لاستئناف الخيط المعلق حتى يتمكن من الاستمرار في التنفيذ. إذا لم يتم تعليق الخيط، فلن يعمل.
إذا (thread.ThreadState = ThreadState.Suspending)
{
Thread.Resume();
}
تم إدراج مثال أدناه لتوضيح وظيفة الترابط البسيطة. يأتي هذا المثال من وثائق المساعدة.
باستخدام النظام؛
باستخدام System.Threading؛
// سيناريو الترابط البسيط: بدء تشغيل طريقة ثابتة
// في الموضوع الثاني
مثال على الطبقة العامة {
// يتم استدعاء أسلوب ThreadProc عند بدء تشغيل مؤشر الترابط.
// يتكرر عشر مرات، ويكتب إلى وحدة التحكم وينتج
// بقية الوقت شريحة في كل مرة، ثم ينتهي.
الفراغ الثابت العام ThreadProc () {
لـ (int i = 0; i < 10; i++) {
Console.WriteLine("ThreadProc: {0}"، i);
// إنتاج شريحة الوقت المتبقية.
Thread.Sleep(0);
}
}
الفراغ الثابت العام الرئيسي () {
Console.WriteLine("الموضوع الرئيسي: ابدأ موضوعًا ثانيًا.");
// يتطلب مُنشئ فئة Thread وجود ThreadStart
// المفوض الذي يمثل الطريقة التي سيتم تنفيذها على
// Thread.C# يبسط عملية إنشاء هذا المفوض.
Thread t = new Thread(new ThreadStart(ThreadProc));
// ابدأ ThreadProc على معالج أحادي، لا يتم الحصول على الخيط
// أي وقت للمعالج حتى ينتج الخيط الرئيسي Uncomment
// Thread.Sleep الذي يتبع t.Start() لمعرفة الفرق.
t.Start();
//Thread.Sleep(0);
لـ (int i = 0; i < 4; i++) {
Console.WriteLine("الموضوع الرئيسي: قم ببعض الأعمال.");
Thread.Sleep(0);
}
Console.WriteLine("الخيط الرئيسي: استدعاء Join()، للانتظار حتى انتهاء ThreadProc.");
t.Join();
Console.WriteLine("الخيط الرئيسي: عاد ThreadProc.Join. اضغط على Enter لإنهاء البرنامج.");
Console.ReadLine();
}
}
ينتج هذا الكود مخرجات مشابهة لما يلي:
الموضوع الرئيسي: ابدأ الموضوع الثاني.
الموضوع الرئيسي: القيام ببعض الأعمال.
الموضوع: 0
الموضوع الرئيسي: القيام ببعض الأعمال.
الموضوع: 1
الموضوع الرئيسي: القيام ببعض الأعمال.
الموضوع: 2
الموضوع الرئيسي: القيام ببعض الأعمال.
الموضوع: 3
الموضوع الرئيسي: استدعاء Join () للانتظار حتى انتهاء ThreadProc.
الموضوع: 4
الموضوع: 5
الموضوع: 6
الموضوع: 7
الموضوع: 8
الموضوع: 9
الموضوع الرئيسي: عاد ThreadProc.Join اضغط على Enter لإنهاء البرنامج.
في Visul C#، توفر مساحة الاسم System.Threading بعض الفئات والواجهات التي تمكن البرمجة متعددة الخيوط. هناك ثلاث طرق لإنشاء مؤشرات الترابط: Thread وThreadPool وTimer. وفيما يلي مقدمة موجزة لكيفية استخدامها واحدة تلو الأخرى.
1. الموضوع
ربما تكون هذه هي الطريقة الأكثر تعقيدًا، ولكنها توفر مجموعة متنوعة من التحكم المرن في سلاسل العمليات. أولاً، يجب عليك استخدام مُنشئه لإنشاء مثيل مؤشر ترابط. معلماته بسيطة نسبيًا، مع مفوض ThreadStart واحد فقط: public Thread(ThreadStart start); لتعيين أولوية التشغيل الخاصة بها أو الحصول عليها (تعداد ThreadPriority: عادي، أدنى، أعلى، أقل من عادي، فوق عادي).
يقوم المثال التالي أولاً بإنشاء مثيلين لمؤشر الترابط t1 وt2، ثم يقوم بتعيين أولوياتهما على التوالي، ثم يبدأ الخيطين (الخيطان متماثلان بشكل أساسي، باستثناء أن مخرجاتهما مختلفة، t1 هو "1" وt2 هو "2" "، وفقًا لنسبة عدد الأحرف التي يخرجونها، يمكننا أن نرى تقريبًا نسبة وقت وحدة المعالجة المركزية التي يشغلونها، وهو ما يعكس أيضًا أولويات كل منهم).
الفراغ الثابت الرئيسي (سلسلة [] الحجج)
{
Thread t1 = new Thread(new ThreadStart(Thread1));
Thread t2 = new Thread(new ThreadStart(Thread2));
t1.Priority = ThreadPriority.BelowNormal;
t2.Priority = ThreadPriority.Lowest;
t1.Start();
t2.Start();
}
الفراغ العام الثابت Thread1 ()
{
لـ (int i = 1; i < 1000; i++)
{// اكتب "1" في كل مرة يتم فيها تشغيل حلقة.
دوست ()؛
Console.Write("1");
}
}
الفراغ العام الثابت Thread2 ()
{
لـ (int i = 0; i < 1000; i++)
{// اكتب "2" في كل مرة يتم فيها تشغيل حلقة.
دوست ()؛
Console.Write("2");
}
}
dosth الفراغ العام الثابت ()
{// يستخدم لمحاكاة العمليات المعقدة
لـ (int j = 0; j <10000000; j++)
{
كثافة العمليات = 15؛
أ = أ*أ*أ*أ;
}
}
نتيجة تشغيل البرنامج أعلاه هي:
11111111111111111111111111111111111111111111111111111111111111111111112
11111111111111111111111111111111111111111111111111111111111111111111112
11111111111111111111111111111111111111111111111111111111111111111111112
من النتائج المذكورة أعلاه، يمكننا أن نرى أن مؤشر الترابط t1 يستهلك وقتًا أطول بكثير لوحدة المعالجة المركزية من t2، وذلك لأن أولوية t1 أعلى من أولوية t2 هي كما يلي الصورة:
121211221212121212121212121212121212121212121212121212121212121
212121212121212121212121212121212121212121212121212121212121212
121212121212121212
من المثال أعلاه، يمكننا أن نرى أن هيكله مشابه لمؤشر ترابط العامل win32، ولكنه أبسط. ما عليك سوى استخدام الوظيفة التي سيتم استدعاؤها بواسطة مؤشر الترابط كمفوض، ثم استخدام المفوض كمعلمة إنشاء مثيل مؤشر الترابط. عندما يتم استدعاء Start() للبدء، سيتم استدعاء الوظيفة المقابلة، وسيبدأ التنفيذ من السطر الأول من تلك الوظيفة.
بعد ذلك، نقوم بدمج خاصية ThreadState للخيط لفهم التحكم في الخيط. ThreadState هو نوع تعداد يعكس حالة مؤشر الترابط. عندما يتم إنشاء مثيل مؤشر الترابط لأول مرة، تكون حالة ThreadState الخاصة به غير قيد التشغيل؛ طريقة Sleep()، لديها طريقتان مثقلتان (Sleep(int)، Sleep(Timespan)))، وهما مجرد تنسيقات مختلفة لتمثيل مقدار الوقت. عندما يتم استدعاء هذه الوظيفة في سلسلة رسائل، فهذا يعني أن سلسلة الرسائل سيتم حظرها لفترة من الوقت (يتم تحديد الوقت من خلال عدد المللي ثانية أو الفترة الزمنية التي تم تمريرها إلى وضع السكون، ولكن إذا كانت المعلمة 0، فهذا يعني تعليق هذا الخيط لتمكين سلاسل الرسائل الأخرى من التنفيذ، وتحديد Infinite لحظر الخيط إلى أجل غير مسمى)، في هذه المرة سوف تصبح ThreadState الخاصة بها WaitSleepJoin. شيء آخر جدير بالملاحظة هو أن وظيفة Sleep () محددة على أنها ثابتة؟ وهذا يعني أيضًا أنه لا يمكن استخدامه مع مثيل مؤشر الترابط، أي أنه لا يوجد استدعاء مشابه لـ t1.Sleep(10)! تمامًا مثل هذا، لا يمكن استدعاء وظيفة Sleep() إلا من خلال الخيط الذي يحتاج إلى "السكون" نفسه، ولا يُسمح باستدعائه بواسطة سلاسل رسائل أخرى، تمامًا كما أن وقت النوم هو مسألة شخصية لا يمكن للآخرين تحديدها . ولكن عندما يكون مؤشر الترابط في حالة WaitSleepJoin ويجب أن ينشط، يمكنك استخدام طريقة Thread.Interrupt، والتي ستطرح ThreadInterruptedException على مؤشر الترابط أولاً (لاحظ طريقة استدعاء Sleep):
الفراغ الثابت الرئيسي (سلسلة [] الحجج)
{
Thread t1 = new Thread(new ThreadStart(Thread1));
t1.Start();
t1.Interrupt();
E.WaitOne();
t1.Interrupt();
t1.Join();
Console.WriteLine("t1 هو النهاية");
}
static AutoResetEvent E = new AutoResetEvent(false);
الفراغ العام الثابت Thread1 ()
{
يحاول
{// يمكن أن نرى من المعلمات أنه سيؤدي إلى السبات
Thread.Sleep(Timeout.Infinite);
}
قبض على (System.Threading.ThreadInterruptedException ه)
{//معالج المقاطعة
Console.WriteLine ("المقاطعة الأولى")؛
}
E.Set();
يحاول
{// ينام
Thread.Sleep(Timeout.Infinite);
}
قبض على (System.Threading.ThreadInterruptedException ه)
{
Console.WriteLine ("المقاطعة الثانية")؛
}// توقف مؤقتًا لمدة 10 ثوانٍ
الموضوع.النوم (10000)؛
}
نتيجة التشغيل هي: المقاطعة الأولى
المقاطعة الثانية
(بعد 10ث) تنتهي t1
من المثال أعلاه، يمكننا أن نرى أن طريقة Thread.Interrupt يمكنها تنبيه البرنامج من حالة الحظر (WaitSleepJoin) وإدخال معالج المقاطعة المقابل، ثم متابعة التنفيذ (تتغير حالة ThreadState أيضًا إلى تشغيل). يجب أن تلاحظ الوظيفة النقاط التالية:
1. لا يمكن لهذه الطريقة فقط تنبيه الحظر الناتج عن السكون، ولكنها فعالة أيضًا لجميع الطرق التي يمكن أن تتسبب في دخول مؤشر الترابط إلى حالة WaitSleepJoin (مثل الانتظار والانضمام). كما هو موضح في المثال أعلاه، عند استخدامه، يجب عليك وضع الطريقة التي تسبب حظر الخيط في كتلة المحاولة، ووضع معالج المقاطعة المقابل في كتلة الصيد.
2. استدعاء المقاطعة على مؤشر ترابط معين إذا كان في حالة WaitSleepJoin، فسوف يدخل إلى معالج المقاطعة المقابل للتنفيذ. إذا لم يكن في حالة WaitSleepJoin في هذا الوقت، فسيتم مقاطعته على الفور عندما يدخل هذه الحالة لاحقًا. . إذا تم استدعاء المقاطعة عدة مرات قبل المقاطعة، فإن الاستدعاء الأول فقط يكون صالحًا، ولهذا السبب استخدمت المزامنة في المثال أعلاه للتأكد من استدعاء الاستدعاء الثاني للمقاطعة بعد المقاطعة الأولى، وإلا فقد يتسبب ذلك في حدوث المقاطعة الثانية. الاستدعاء ليس له أي تأثير (إذا تم استدعاؤه قبل المقاطعة الأولى). يمكنك محاولة إزالة المزامنة ومن المرجح أن تكون النتيجة: المقاطعة الأولى
يستخدم المثال أعلاه أيضًا طريقتين أخريين لجعل مؤشر الترابط يدخل في حالة WaitSleepJoin: استخدام كائن المزامنة وأسلوب Thread.Join. استخدام طريقة الانضمام بسيط نسبيًا، وهذا يعني أن الخيط الحالي الذي يستدعي هذه الطريقة يحظر حتى ينتهي الخيط الآخر (t1 في هذا المثال) أو يمر الوقت المحدد (إذا كان يستغرق أيضًا معلمة زمنية إذا وجدت). إذا حدث الشرط (إن وجد)، فإنه ينهي على الفور حالة WaitSleepJoin ويدخل في حالة التشغيل (يمكن تحديد الحالة بناءً على القيمة المرجعة لطريقة .Join. إذا كان صحيحًا، فسيتم إنهاء مؤشر الترابط؛ وإذا كان خطأ، انتهى الوقت). يمكن أيضًا تعليق مؤشر الترابط باستخدام أسلوب Thread.Suspend. عندما يكون مؤشر الترابط في حالة التشغيل ويتم استدعاء أسلوب التعليق عليه، فإنه سيدخل إلى حالة SuspendRequested، لكن لن يتم تعليقه على الفور حتى يصل مؤشر الترابط إلى حالة آمنة. نقطة توقف الخيط، وعند هذه النقطة سيدخل في حالة التعليق. إذا تم استدعاؤه على مؤشر ترابط معلق بالفعل، فسيكون غير صالح لاستئناف العملية، فقط اتصل بـ Thread.Resume.
آخر ما نتحدث عنه هو تدمير سلاسل الرسائل، يمكننا استدعاء طريقة Abort على الخيط الذي يحتاج إلى التدمير، وسوف يرمي ThreadAbortException على هذا الخيط. يمكننا وضع بعض التعليمات البرمجية في مؤشر الترابط في كتلة المحاولة، ووضع رمز المعالجة المقابل في كتلة الالتقاط المقابلة. عندما يقوم الخيط بتنفيذ التعليمات البرمجية في كتلة المحاولة، إذا تم استدعاء الإجهاض، فسوف ينتقل إلى كتلة الالتقاط المقابلة. تم تنفيذه داخل كتلة الالتقاط، وسوف ينتهي بعد تنفيذ التعليمات البرمجية في كتلة الالتقاط (إذا تم تنفيذ ResetAbort داخل كتلة الالتقاط، فسيكون الأمر مختلفًا: سيلغي طلب الإجهاض الحالي ويستمر في التنفيذ للأسفل. لذلك، إذا قمت بذلك. تريد التأكد من انتهاء سلسلة الرسائل، فمن الأفضل استخدام Join، كما في المثال أعلاه).
2. ثريدبول
يعد Thread Pool (ThreadPool) طريقة بسيطة نسبيًا، وهو مناسب للمهام القصيرة التي تتطلب سلاسل رسائل متعددة (مثل بعض سلاسل الرسائل التي يتم حظرها غالبًا). نظرًا لأن كل عملية تحتوي على تجمع مؤشرات ترابط واحد فقط، وبالطبع يحتوي كل مجال تطبيق على تجمع مؤشرات ترابط واحد فقط (خط)، فستجد أن وظائف الأعضاء في فئة ThreadPool كلها ثابتة! عند استدعاء ThreadPool.QueueUserWorkItem، ThreadPool.RegisterWaitForSingleObject، وما إلى ذلك لأول مرة، سيتم إنشاء مثيل تجمع مؤشرات الترابط. فيما يلي مقدمة للوظيفتين الموجودتين في تجمع مؤشرات الترابط:
public static bool QueueUserWorkItem( // يُرجع صحيحًا إذا كانت المكالمة ناجحة
WaitCallback callBack,// المفوض الذي يتم استدعاؤه بواسطة مؤشر الترابط المراد إنشاؤه
حالة الكائن // تم تمرير المعلمات إلى المفوض
)// إنها وظيفة أخرى محمّلة بشكل زائد مشابهة، باستثناء أن المفوض لا يأخذ أي معلمات. قام تجمع سلاسل الرسائل بإنشاء سلاسل رسائل إذا كان العدد محدودًا (القيمة الافتراضية هي 25)، فسيتم إنشاء هذا الموضوع، وإلا فسيتم وضعه في قائمة الانتظار في تجمع سلاسل الرسائل والانتظار حتى يتوفر له سلاسل رسائل.
ثابت عام RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,//سيتم تسجيل WaitHandle
WaitOrTimerCallback callBack، // مندوب استدعاء الموضوع
حالة الكائن، // تم تمرير المعلمات إلى المفوض
int TimeOut,// المهلة، الوحدة بالمللي ثانية،
bool ExecuteOnlyOnce file:// ما إذا كان سيتم التنفيذ مرة واحدة فقط
);
المفوض العام باطل WaitOrTimerCallback(
حالة الكائن، // أي المعلمات التي تم تمريرها إلى المفوض
bool timedOut//true يعني بسبب استدعاء المهلة، وإلا فهو يعني waitObject
);
وظيفة هذه الوظيفة هي إنشاء مؤشر ترابط انتظار. بمجرد استدعاء هذه الوظيفة، سيتم إنشاء هذا الموضوع في حالة "محظورة" حتى تتغير المعلمة waitObject إلى الحالة المنتهية أو يصل الوقت المحدد تجدر الإشارة إلى أن "الحظر" هذا يختلف تمامًا عن حالة WaitSleepJoin الخاصة بمؤشر الترابط: عندما يكون مؤشر الترابط في حالة WaitSleepJoin، ستقوم وحدة المعالجة المركزية بتنشيطه بانتظام لاستقصاء معلومات الحالة وتحديثها، ثم الدخول إلى حالة WaitSleepJoin مرة أخرى. يعد تبديل الخيط كثيف الاستخدام للموارد ؛ ولن تقوم وحدة المعالجة المركزية بالتبديل إلى هذا الخيط قبل تشغيله ، ولا تستهلك وقت وحدة المعالجة المركزية ولا تضيع وقت تبديل الخيط تعرف متى لتشغيله؟ في الواقع، سيقوم تجمع الخيوط بإنشاء بعض الخيوط المساعدة لمراقبة شروط التشغيل هذه، بمجرد استيفاء الشروط، سيتم تشغيل الخيوط المقابلة، بالطبع، تستغرق هذه الخيوط المساعدة نفسها وقتًا أيضًا، ولكن إذا كنت بحاجة إلى إنشاء المزيد من الانتظار أصبحت المزايا أكثر وضوحًا لاستخدام تجمع الخيوط. انظر المثال أدناه:
static AutoResetEvent ev=new AutoResetEvent(false);
int العام الثابت الرئيسي (سلسلة [] الحجج)
{ ThreadPool.RegisterWaitForSingleObject (
إيف,
WaitOrTimerCallback الجديد (WaitThreadFunc)،
4,
2000،
خطأ // يشير إلى أنه سيتم إعادة ضبط المؤقت في كل مرة تكتمل فيها عملية الانتظار حتى تسجيل الخروج والانتظار.
);
ThreadPool.QueueUserWorkItem (new WaitCallback (ThreadFunc),8);
الموضوع.النوم (10000)؛
العودة 0؛
}
ThreadFunc الفراغ العام الثابت (الكائن ب)
{ Console.WriteLine ("الكائن هو {0}"، ب)؛
ل(int i=0;i<2;i++)
{ الموضوع.النوم (1000)؛
ev.Set();
}
}
الفراغ العام الثابت WaitThreadFunc (object b، bool t)
{ Console.WriteLine ("الكائن هو {0}،t هو {1}"،b،t)؛
}
نتيجة عملها هي:
الكائن هو 8
الكائن هو 4,t خطأ
الكائن هو 4,t خطأ
الكائن هو 4,t صحيح
الكائن هو 4,t صحيح
الكائن هو 4,t صحيح
من النتائج المذكورة أعلاه، يمكننا أن نرى أن مؤشر الترابط ThreadFunc تم تشغيله مرة واحدة، وتم تشغيل WaitThreadFunc 5 مرات. يمكننا الحكم على سبب بدء هذا الموضوع من المعلمة bool t في WaitOrTimerCallback: إذا كان t خطأ، فهذا يعني الانتظار، وإلا فهو بسبب انتهاء المهلة. بالإضافة إلى ذلك، يمكننا أيضًا تمرير بعض المعلمات إلى الخيط من خلال الكائن b.
3. الموقت
إنه مناسب للطرق التي يجب استدعاؤها بشكل دوري، ولا يعمل في مؤشر الترابط الذي أنشأ المؤقت، بل يتم تشغيله في مؤشر ترابط منفصل مخصص تلقائيًا بواسطة النظام. وهذا مشابه لأسلوب SetTimer في Win32. هيكلها هو:
الموقت العام(
رد اتصال TimerCallback,//طريقة الاتصال
حالة الكائن، // تم تمرير المعلمات إلى رد الاتصال
int DueTime,//كم من الوقت سيستغرق بدء رد الاتصال؟
فترة int// الفاصل الزمني لاستدعاء هذه الطريقة
); // إذا كانت قيمة DueTime تساوي 0، فسيقوم رد الاتصال بتنفيذ المكالمة الأولى على الفور. إذا كانت قيمة DueTime لا نهائية، فلن يستدعي رد الاتصال أسلوبه. تم تعطيل المؤقت، ولكن يمكن إعادة تمكينه باستخدام أسلوب التغيير. إذا كانت الفترة 0 أو لا نهائية، وكان DueTime ليس لانهائيًا، فسيستدعي رد الاتصال أسلوبه مرة واحدة. تم تعطيل السلوك الدوري للمؤقت، ولكن يمكن إعادة تمكينه باستخدام أسلوب التغيير. إذا كانت الفترة تساوي صفر (0) أو لا نهائية، وكان DueTime ليس لانهائيًا، فسيقوم رد الاتصال باستدعاء الأسلوب الخاص به مرة واحدة. تم تعطيل السلوك الدوري للمؤقت، ولكن يمكن إعادة تمكينه باستخدام أسلوب التغيير.
إذا أردنا تغيير الفترة ووقت الاستحقاق للمؤقت بعد إنشائه، فيمكننا تغييرهما عن طريق استدعاء طريقة تغيير المؤقت:
تغيير المنطق العام(
int الواجب الوقت,
فترة كثافة العمليات
);// من الواضح أن المعلمتين المتغيرتين تتوافقان مع المعلمتين في Timer
int العام الثابت الرئيسي (سلسلة [] الحجج)
{
Console.WriteLine ("الفترة هي 1000")؛
Timer tm=new Timer (new TimerCallback (TimerCall)،3,1000,1000);
موضوع.النوم (2000)؛
Console.WriteLine ("الفترة هي 500")؛
tm.Change (0,800);
الموضوع.النوم (3000)؛
العودة 0؛
}
TimerCall العام الفارغ الثابت (الكائن ب)
{
Console.WriteLine ("timercallback؛ b هو {0}"،b)؛
}
نتيجة عملها هي:
الفترة هي 1000
timercallback؛ ب هو 3
timercallback؛ ب هو 3
الفترة 500
timercallback؛ ب هو 3
timercallback؛ ب هو 3
timercallback؛ ب هو 3
timercallback؛ ب هو 3
تلخيص
من المقدمة الموجزة أعلاه، يمكننا أن نرى المناسبات التي يتم استخدامها فيها على التوالي: Thread مناسب للمناسبات التي تتطلب تحكمًا معقدًا في سلاسل الرسائل؛ ThreadPool مناسب للمهام القصيرة التي تتطلب سلاسل رسائل متعددة (مثل بعض المواضيع التي يتم حظرها غالبًا). ); Timer مناسب للطرق التي يجب استدعاؤها بشكل دوري. وطالما أننا نفهم خصائص استخدامها، يمكننا اختيار الطريقة المناسبة جيدًا.