Threading تعتبر من أهم المفاهيم فى تكنولوجيا تطوير البرمجيات, والمفهوم الاساسى من threading هو كيفية إنجاز أكثر من عملية متزمنة فى وقت واحد. كل عملية من تلك العمليات تأخذ Thread معين لكى تسلك طرقها فى التنفيذ. بعض ال Threading يمكن أن تتوقف لكى تستقبل بيانات من جهة أخرى لكى يكتمل مسارها على سبيل المثال لو موقع ويب يمتلك Method معينه هذه ال Method يتطلب أن تقف وقت معين فى التنفيذ لكى يتم إرسال إليها Resources من ال Server. عن طريق ال Thread يمكنك أن تمتلك أكثر من Processor لتنفيذ أكثر من عملية فى وقت واحد, أو إذا كنت بالفعل تمتلك أكثر من Physical Processor ال Threading تجعلك تستخدم الإستخدام الأمثل لتلك ال Processors
الهدف من الدرس:

·         Develop multithreaded .NET Framework applications. (Refer System.Threading namespace).

§  Thread class
§  ThreadPool class
§  ThreadStart delegate and ParameterizedThreadStart delegate
§  Timeout class, Timer class, TimerCallback delegate, WaitCallback delegate,WaitHandle class, and WaitOrTimerCallback delegate
§  ThreadExceptionEventArgs class and ThreadExceptionEventHandler class
§  ThreadState enumeration and ThreadPriority enumeration
§  ReaderWriterLock class
§  AutoResetEvent class and ManualResetEvent class
§  IAsyncResult Interface (Refer System namespace)
§  EventWaitHandle class, RegisteredWaitHandle class, SendOrPostCallback delegate, and IOCompletionCallback delegate
§  Interlocked class, NativeOverlapped structure, and Overlapped class
§  ExecutionContext class, HostExecutionContext class, HostExecutionContextManager class, and ContextCallback delegate
§  LockCookie structure, Monitor class, Mutex class, and Semaphore class


الدرس الأول: Creating Thread
Threading هى أساس التطبيقات عالية الأداء, System.Threading Namespace تمتلك كل الأدوات لإنشاء Thread وإدارة العديد من Threads.
Simple Thread

لكى نبدء إنشاء ال Thread يجب أن نتطلع أولا على Thread Class. ال Thread Class يمكن من خلاله إنشاء وعمل بدء لل Thread والجدول التالى يوضح معظم الخواص أو Properties الموجوده فى Thread Class


Description
Name
Gets a value indicating that the current thread is currently executing.
IsAlive
Gets or sets whether the thread runs as a background thread.
IsBackground
Gets whether this thread is a thread in the thread pool.
IsThreadPoolThread
Gets a number to identify the current thread. Not the same as the operating systems thread ID.
ManagedThreadId
Gets or sets a name associated with the thread.
Name
Gets or sets the priority of the thread.
Priority
Gets the ThreadState value for the thread.
ThreadState

والجدول التالى يوضح ال Methods الموجوده فى Thread Class
Description
Name
Raises a ThreadAbortException on the thread to indicate that the thread should be aborted.
Abort
Raises a ThreadInterruptedException when a thread is in a blocked state (ThreadState.WaitJoinSleep). If the thread
never blocks, the interruption never happens.
Interrupt
Blocks the calling thread until the thread terminates.
Join
Sets a thread to be scheduled for execution.
Start

الجدول التالى يوضح Static Thread Properties والتى يتم إستدعائها بإسم الكلاس ثم إسم ال Property بدون أن نأخذ Object من الكلاس (مبدء Object Oriented Programming).
 Description
Name
Gets the current ThreadContext object related to the current thread
CurrentContext
Gets and sets the user associated with the current thread
CurrentPrincipal
Gets the current running thread
CurrentThread

والجدول التالى يوضح Static Thread Methods.
Description
Name
Used to notify the host that code to be executed cannot be aborted safely. Aborting a thread between a BeginCriticalRegion and EndCriticalRegion might leave an AppDomain in an unsafe state.
BeginCriticalRegion
Used to notify the host that you have reached the end of a critical region.
EndCriticalRegion
Gets the AppDomain associated with the current running thread.
GetDomain
Gets a unique identifier for the AppDomain associated with the currently running thread.
GetDomainID
Cancels an Abort request for the currently running thread
ResetAbort
Blocks the current thread for a certain amount of time. Relinquishes execution to other threads to allow them to do work.
Sleep
Blocks the current thread for a certain number of iterations. Does not relinquish execution to other threads.
SpinWait
Reads the latest version of a field value regardless of which processor in a multiprocessor environment wrote the value.
VolatileRead
Writes a field value immediately to ensure it is available to all processors.
VolatileWrite

والجدول التالى يوضح ال Enumeration أو ال Option المتاحة فى ThreadState Property
Description
Name
The thread has stopped.
Aborted
The thread has been requested to abort, but the abort is still pending and has not received the
ThreadAbortException.
AbortRequested
The thread is running as a background thread.
Background
The thread has started.
Running
The thread has stopped.
Stopped
The thread is being requested to stop. For internal use only.
StopRequested
The thread has been created, but the Thread.Start method has not been called.
Unstarted
The thread is blocked as a call to Monitor.Wait, Thread.Sleep, or Thread.Join.
WaitSleepJoin

لكى يتم إنشاء Thread و عمل له بدء نتبع الإجراءات التالية:
1-     يجب أن نكتب ال Method التى نريد أن تنفذ فى Thread منفصل عن ال Main Thread بدون Return Value وأيضا بدون Argument.

static void SimpleWork()
{
Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);
}
2-     يتم إنشاء ThreadStart Delegate ويتم تمرير له ال Method التى تم إنشائها سابقا.
3-     يتم إنشاء Object من Thread Class ويتم تمرير له ال Delegate Object.
4-     بعد ذلك يتم إستدعاء Thread.Start لكى يتم تنفيذ ال Thread الجديد.
كما يلى:

ThreadStart operation = new ThreadStart(SimpleWork);
Thread theThread = new Thread(operation);
theThread.Start();

عندما Start Method يتم إستدعائها يتم تنفيذ SimpleWork فى Thread منفصل.


Using Multiple Thread

يمكن أيضا أن نستخدم أكثر من Thread فى البرنامج, المثال القادم يوضح كيف نستخدم أكثر من Thread على SimpleWork Method كما يلى:

static void SimpleWork()
{
for (int x = 1; x <= 10; ++x)
{
Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);
// Slow down thread and let other threads work
Thread.Sleep(10);
}
}


ThreadStart operation = new ThreadStart(SimpleWork);
for (int x = 1; x <= 5; ++x)
{
// Creates, but does not start, a new thread
Thread theThread = new Thread(operation);
// Starts the work on a new thread
theThread.Start();
}
هذا الكود سوف ينفذ العملية فى Five Thread منفصله.

عندما يكثر لدينا ال Threads والمطلوب أن ننفذ Thread معين قبل باقى ال Threads ونجعل ال Application أو Main Thread ينتظر أن ينفذ ال Thread نستخدم فى ذلك The Join Method

theThread.Join();

Join Method تخبر ال Application أن ينتظر حتى يتم إستكمال ال Thread, والمثال القادم يوضح أن يوجد خمس Threads يتم تنفيذ كل Thread منفرد ثم يتم تنفيذ الذى يليه عن طريق Join Method

static void Main(string[] args)
        {
            ThreadStart operation = new ThreadStart(SimpleWork);
            Thread[] theThreads = new Thread[5];
            for (int x = 0; x < 5; ++x)
            {
                // Creates, but does not start, a new thread
                theThreads[x] = new Thread(operation);
                // Starts the work on a new thread
                theThreads[x].Start();
                // Wait for each thread to complete
                theThreads[x].Join();
            }
           
        }

static void SimpleWork()
        {
            for (int x = 1; x <= 10; ++x)
            {
                Console.WriteLine("Thread: {0}",
                Thread.CurrentThread.ManagedThreadId);
                // Slow down thread and let other threads work
                Thread.Sleep(10);
            }
        }
    

Thread Priority

الكلاس المسئول عن جلب أو وضع أولوية لتنفيذ ال Thread هو Thread Class بإستخدام ThreadPriority enumeration و ThreadPriority enumeration يحتوى على القيم التالية:

Description
Name
The highest priority
Highest
Higher priority than Normal
AboveNormal
The default priority
Normal
Lower than Normal
BelowNormal
The lowest priority
Lowest

مثال:
theThreads1.Priority = ThreadPriority.Lowest;

Passing Data to Threads

فى بعض الأحيان نريد أن نمرر معلومة لل Threads وذلك لا يمكن فعله بإستخدام StartThread Delegate ونستبد ذلك بإستخدام ParameterizedStartThread والذى يخصص ل Method Signature خاصه تحتوى على One Parameter من نوع Object ولا ترجع قيمة No return Value هذه ال Method تكون كالتالى:


static void WorkWithParameter(object o)
        {
            string info = (string)o;
            for (int x = 0; x < 10; ++x)
            {
                Console.WriteLine("{0}: {1}", info,
                Thread.CurrentThread.ManagedThreadId);
                // Slow down thread and let other threads work
                Thread.Sleep(10);
            }
        }

ParameterizedThreadStart operation = new ParameterizedThreadStart(WorkWithParameter);
// Creates, but does not start, a new thread
Thread theThread = new Thread(operation);
// Starts the work on a new thread
theThread.Start("Hello");
// A Second Thread with a different parameter
Thread newThread = new Thread(operation);
newThread.Start("Goodbye");

نلاحظ أن Start Method يتم تمرير من خلالها ال Argument الموجود فى ال Method المراد تنفذها فى ال Thread.


 Stopping Threads

التحكم فى Threads الموجوده فى ال Application أحيانا يتطلب توقيف لبعض ال Threads والألية الأساسية لعمل توقيف لل Thread عن طريق إستخدام Thread.Abort Method, عندما يتم إستدعاء Thread.Abort نظام ال Thread يبدء فى تجهيز ThreadAbortException لتمريره.

مثال:
static void Main(string[] args)
        {
            ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork);
            Thread myThread = new Thread(myThreadDelegate);
            myThread.Start();
            Thread.Sleep(100);
            Console.WriteLine("Main - aborting my thread.");
            myThread.Abort();
            Console.WriteLine("Main ending.");
        }
        public class ThreadWork
        {
            public static void DoWork()
            {
                try
                {
                    for (int i = 0; i < 100; i++)
                    {
                        Console.WriteLine("Thread - working.");
                        Thread.Sleep(100);
                    }
                }
                catch (ThreadAbortException e)
                {
                    Console.WriteLine("Thread - caught ThreadAbortException - resetting.");
                    Console.WriteLine("Exception message: {0}", e.Message);
                }
            }
        }

فى حالة كتابة ThreadAbortException أو لا فإن Thread سوف يتوقف.

عند عمل Abort ل Thread فإن الكود سوف يتم توقفه داخل ال Thread دون معرفه أين سوف ينتهى وهذا يجعلنا نفقد السيطره على ال Thread ولو إفترضا أننا نريد تنفيذ كود معين قبل أن يحدث Abort لل Thread نضع الكود داخل Two Method الأولى Thread.BeginCriticalRegion والثانية Thread.EndCriticalRegion وهذا يجعل الكود داخل ال Two Method وكأنهم One line of Code

بعد أن إنتهينا من الدرس الأول, المثال التالى يوضح كيفيه تشغيل أكثر من Thread على Method بتعد من 1 إلى 10.

static void Main(string[] args)
        {
            ThreadStart starter = new ThreadStart(Counting);
            Thread first = new Thread(starter);
            Thread second = new Thread(starter);
            first.Start();
            second.Start();
            first.Join();
            second.Join();
            Console.Read(); 
        }
        static void Counting()
        {
            {
               for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("Count: {0} - Thread: {1}", i, Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(10);
                }
            }
        }

0 التعليقات

إرسال تعليق