استفاده از thread ها در C#
مقدمه :
Thread ها ابزاری مفید هستند که به کاربر اجازه می دهند تا اعمالی را به صورت موازی
(Parallel) و همزمان انجام دهد. با استفاده از Thread ها، از امکانات MultiTasking
در یک برنامه استفاده می کنید. در ضمن می توانید یک قسمت از برنامه را متوقف و یا به
جریان بیندازید. در استفاده از Threadها بسیار مراقب باشید چون منابع شما محدود هستند.
Threadها هنگامی که باید منتظر پاسخ بخشی دیگر از برنامه باشید، بسیار به کار می آیند
و شما می توانید در حالی که بخشی از برنامه متوقف است و منتظر پاسخ است بقیه قسمت ها
را پیش ببرید که سرعت برنامه های شما را به طرز قابل ملاحظه ای افزایش می دهد..
در C# کلاسهایی برای استفاده از Thread ها وجود دارندکه در System.Threading قرار
دارند. در ادامه یک مورد ساده ی استفاده از Thread شرح داده می شود. امید است که مورد
استفاده واقع شود.
کار با Thread ها :
در ابتدا باید یک Object از نوع System.Threading.Thread ایجاد کنید. کلاس Thread
تنها یک ایجادکننده (Constructor) دارد که یک ThreadStart (که یک Delegate است) می
گیرد. برای توابع static می توان مستقیما نام تابع را ارسال کرد. تابع نوشته شده باید
هیچ پارامتری نداشته باشد و هیچ مقداری را نیز برنگرداند (یعنی void باشد) به این علت
که تابع اصلی این گونه تعریف شده است.
public static
void MyCallbackFunction()
{
while (true)
{
System.Console.WriteLine(“
Hey!, My Thread Function Running”);
}
}
Thread MyThread = new Thread(new
ThreadStart (MyCallbackFunction));
MyThread.Start();
بعد از ایجاد Thread می توانید آن را با Start، شروع کنید. Thread را می توانید
با Abort بکشید که باعث ایجاد یک ThreadAbortException خواهد شد. با Suspend و Resume
هم می توانید Thread را متوقف و یا مجددا به حرکت بیندازید.
Thread یکی از حالت های زیر را دارد که با ThreadState قابل مشاهده
است:
Unstarted |
Thread is Created within the common language
run time but not Started still. |
Running |
After a Thread calls Start method |
WaitSleepJoin |
After a Thread calls its wait or Sleep or
Join method. |
Suspended |
Thread Responds to a Suspend method call. |
Stopped |
The Thread is Stopped, either normally or
Aborted. |
|
اولویت Thread نیز با ThreadPriority تعیین می شود که یکی از حالت های زیر را
دارد:
Lowest, BelowNormal, Normal, AboveNormal, Highest
که در حالت عادی Normal است.
مثال های بیشتر برای MultiTreading
برنامه زیر یک برنامه ی مفید و ساده برای دریافتن مفهوم MultiThread است
که به همراه خروجی برنامه آورده می شود:
using System;
using System.Threading;
class Tester
{
static void
Main( )
{
// make an instance of this class
Tester t = new Tester( );
// run outside static Main
t.DoTest( );
}
public void
DoTest( )
{
// create a thread for the Incrementer
// pass in a ThreadStart delegate
// with the address of Incrementer
Thread t1 = new Thread(
new ThreadStart(Incrementer) );
// create a thread for the Decrementer
// pass in a ThreadStart delegate
// with the address of Decrementer
Thread t2 =
new Thread(
new ThreadStart(Decrementer) );
// start the threads
t1.Start( );
t2.Start( );
}
// demo function, counts up to 1K
public
void Incrementer( )
{
for (int
i =0;i<1000;i++)
{
Console.WriteLine("Incrementer: {0}", i);
}
}
// demo function, counts down from 1k
public
void Decrementer( )
{
for (int
i = 1000;i>=0;i--)
{
Console.WriteLine("Decrementer: {0}", i);
}
}
}
Output:
Incrementer: 102
Incrementer: 103
Incrementer: 104
Incrementer: 105
Incrementer: 106
Decrementer: 1000
Decrementer: 999
Decrementer: 998
Decrementer: 997
پیوند زدن Thread ها و متوقف کردن آنها
بااستفاده از join می توانید Thread ها را به هم وصل کنید و با Seleep برای
لحظاتی چند متوقف کنید. یک نمونه ی ساده در زیر آمده است :
using System;
using System.Threading;
class Tester
{
private int
counter = 0;
static void
Main( )
{
// make an instance of this class
Tester t = new Tester( );
// run outside static Main
t.DoTest( );
}
public void
DoTest( )
{
Thread t1 = new Thread(
new ThreadStart(Incrementer) );
t1.IsBackground=true;
t1.Name = "ThreadOne";
t1.Start( );
Console.WriteLine("Started thread {0}",
t1.Name);
Thread t2 = new Thread(
new ThreadStart(Incrementer) );
t2.IsBackground=true;
t2.Name = "ThreadTwo";
t2.Start( );
Console.WriteLine("Started thread {0}",
t2.Name);
t1.Join( );
t2.Join( );
// after all threads end, print a message
Console.WriteLine("All my threads are done.");
}
// demo function, counts up to 1K
public
void Incrementer( )
{
try
{
while (counter < 1000)
{
int temp = counter;
temp++; // increment
// simulate some work
in this method
Thread.Sleep(1);
// assign the decremented
value
// and display the
results
counter = temp;
Console.WriteLine("Thread {0}. Incrementer:
{1}",Thread.CurrentThread.Name,counter);
}
}
catch (ThreadInterruptedException)
{
Console.WriteLine("Thread {0} interrupted! Cleaning
up...",Thread.CurrentThread.Name);
}
finally
{
Console.WriteLine("Thread {0} Exiting.
",Thread.CurrentThread.Name);
}
}
}
Output:
Started thread ThreadOne
Started thread ThreadTwo
Thread ThreadOne. Incrementer: 1
Thread ThreadOne. Incrementer: 2
Thread ThreadOne. Incrementer: 3
Thread ThreadTwo. Incrementer: 3
Thread ThreadTwo. Incrementer: 4
Thread ThreadOne. Incrementer: 4
Thread ThreadTwo. Incrementer: 5
Thread ThreadOne. Incrementer: 5
Thread ThreadTwo. Incrementer: 6
Thread ThreadOne. Incrementer: 6
استفاده از InterLock
یکی دیگر از امکاناتی که در اختیار دارید، امکان InterLock است که براساس آن می
توانید برای برنامه های در حال اجرا Lock تعریف کنید. برای این کار C# تابعی به نام
InterLock در اختیار شما قرار می دهد که شامل دو تابع Increment و Decrement است.
نمونه ی ساده ای از نحوه استفاده و خروجی تابع در زیر آمده است:
public void
Incrementer( )
{
try
{
while (counter < 1000)
{
Interlocked.Increment(ref
counter);
// simulate some work in this method
Thread.Sleep(1);
// assign the decremented value
// and display the results
Console.WriteLine("Thread {0}. Incrementer: {1}",
Thread.CurrentThread.Name,counter);
}
}
}
Output (excerpts):
Started thread ThreadOne
Started thread ThreadTwo
Thread ThreadOne. Incrementer: 1
Thread ThreadTwo. Incrementer: 2
Thread ThreadOne. Incrementer: 3
Thread ThreadTwo. Incrementer: 4
Thread ThreadOne. Incrementer: 5
Thread ThreadTwo. Incrementer: 6
Thread ThreadOne. Incrementer: 7
Thread ThreadTwo. Incrementer: 8
Thread ThreadOne. Incrementer: 9
Thread ThreadTwo. Incrementer: 10
Thread ThreadOne. Incrementer: 11
Thread ThreadTwo. Incrementer: 12
Thread ThreadOne. Incrementer: 13
Thread ThreadTwo. Incrementer: 14
Thread ThreadOne. Incrementer: 15
Thread ThreadTwo. Incrementer: 16
Thread ThreadOne. Incrementer: 17
Thread ThreadTwo. Incrementer: 18
Thread ThreadOne. Incrementer: 19
Thread ThreadTwo. Incrementer: 20