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 system’s 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 التعليقات
إرسال تعليق