pillinetwork hesabınızla giriş yapın.

C# Basit thread kullanımı…

Bilgisayarda her açılan program kendisi için bir kanal açar ve komutları bu kanal üzerinden işlemciye iletir. Siz programınızda birden fazla işlemi aynı anda kullancaksanız normal durumda bu işlemler aynı kanalı kullanacaktır. Bu işlemlerden birisi sonsuz döngüye girdiğinde kanalı işgal edeceği için diğer işlemler bu kanalı kullanamayacak ve programınız kilitlenecektir. Bu duruma örnek olarak aşaığdaki kodu gösterebiliriz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int i = 0;
bool Dur = false;
private void Say()
{
while (true)
{
if (Dur)
break;
i++;
}
Dur = false;
}
private void btnBasla_Click(object sender, EventArgs e)
{
Say();
}
private void btnDur_Click(object sender, EventArgs e)
{
Dur = true;
}
}

Burada “btnBasla” butonuna bastıktan sonra program sonuz döngüye girip programa tahsis edilen kanalı tıkayacağı için “btnDur” butonuna basamayacaksınız ve programınız kitlenecektir.
Bu durumdan kurtulmak için “Say” metotu için ayrı bir kanal açmalıyız. Bu sayede “Say” metotu kendi kanalını çok yoğun kullansa bile programımızın geri kalan kısmı ayrı bir kanal kullanacağı için diğer kontrollerimizin çalışmasında bir aksaklık olmayacaktır.
Bunun için Therad sınıfını kullanacağız. Bu sınıftan türettiğimiz nesnemize “Say” metotunu atayarak bu metot için ayrı bir kanal atamış olacağız.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int i = 0;
bool Dur = false;
Thread IsParcasi;
private void Say()
{
while (true)
{
if (Dur)
break;
i++;
}
Dur = false;
}
private void btnBasla_Click(object sender, EventArgs e)
{
//Say();
if (IsParcasi.ThreadState == ThreadState.Suspended) // IsParcasi askıya alınmışsa
IsParcasi.Resume(); // Devam ettir.
else // Değilse
IsParcasi.Start(); // Başlat
}
private void btnDur_Click(object sender, EventArgs e)
{
//Dur = true;
IsParcasi.Suspend();
}
private void Form1_Load(object sender, EventArgs e)
{
IsParcasi = new Thread(new ThreadStart(Say));
}
}

Birde forma label atalım ve i değerini bu labeli yazdırmayı deneyelim. Bunun için “Say” metotunu şu şekilde değiştirelim…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void Say()
{
while (true)
{
if (Dur)
break;
i++;
label1.Text = i.ToString();
}
Dur = false;
}

“btnBasla” butonuna basıldığında oluşan “Cross Thread” olayından dolayı programımız hata verecektir. Bu durumun sebebi iş parçacıkları arası veri aktarımıdır. Bu durumu değişik yollarla aşabiliriz ancak biz şimdilik işin kolayına kaçıp Form umuzun yapıcı metoduna aşağıdaki gibi değiştirdiğimizde programımız sorunsuz çalışacaktır.
1
2
3
4
5
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}

İnsanoğlunun istekleri bitmez  Birde bu artış saniyede bir olsun istersek ne yapmalıyız ? Thread sınıfının sleep metotu ile bulunduğumuz “Thread” i istediğimiz bir süre duraklataıp tekrar devam etmesini sağlayabiliriz. Metotun aldığı parametre ile Thread in kaç milisaniye bekletilceğini belirleyebiliriz. Say metotunu aşağıdaki gibi değiştirirsek bu isteğimizi gerçekleitirmiş oluruz.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void Say()
{
while (true)
{
if (Dur)
break;
i++;
label1.Text = i.ToString();
Thread.Sleep(1000);
}
Dur = false;
}

Bu kadar kod yazmışken olayı işlevsel hale getirelim ve label a sadece rakam değil salise saniye dakika saat şeklinde gösterim yapalım. Say metotunu aşağıdaki gibi değiştirdiğimizde artık kendi kronometremizi oluşturmuş olduk Hayırlı olsun…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int Salise = 1;
int Saniye = 0;
int Dakika = 0;
int Saat = 0;
private void Say()
{
while (true)
{
if (Dur)
break;
i++;
Salise = i%10;
if (Salise == 0)
{
Saniye++;
if (Saniye == 60)
{
Saniye = 0;
Dakika++;
if (Dakika == 60)
{
Dakika = 0;
Saat++;
}
}
}
label1.Text = Saat.ToString() + ":" + Dakika.ToString() + ":" + Saniye.ToString() + "." + Salise.ToString();
Thread.Sleep(100);
}
Dur = false;
}

/* Etiketler: , , */
/* CodeMachine yazdı. 11 Ocak 2010 17:57. 5 yorum var */

Yorumlar

CheckForIllegalCrossThreadCalls kontrolünü iptal etmek yerine gui threadde çalışan nesneler için invoke kullanmak daha doğru.

Ayrıca thread yaratmak yüklü bir iştir, bu sebeple sürekli thread yaratmak yerine threadpool'u kullanmanız daha iyi olur.

@muratmoon bilgilendirme için teşekkürler. zaten benim başlıktata "basit" yazıyor. yani thread nedir ne işe yarar sorularını yanıtlamaya çalıştım. bu kısımları anladıktan sonra bu temelde program yazarken tavsiyelerinize uyulması lazım. zaten CheckForIllegalCrossThreadCalls komutunu kullanmadan önce işin kolayına kaçıldığınıda belirttim. invoke kısmına girseydik belki biraz daha dallanacaktı konu. inşallah bunun üstüne dediğiniz konulara değinilen makaleler eklenerek site zenginleşmiş olur....

Sizi kötülemek için yazmadım zaten bu konu ile ilgilenen olursa fikri olsun diye yazmıştım.

@muratmoon biiyorum kötülemediğinizi, bende makaleyi neden yazdığımı açıkladım. Bigilendirdiğin için tekrar teşekkürler...

Ayrıca "Dur" ve "i" değişkenlerini ReaderWriterLock ile garantiye almak lazım uygulamada ileride ciddi sıkıntılar çıkmasın.

/* M.Bayer */

üye olunpillinetwork sitelerine yorum ekleyebilmek ve daha fazlası için, üye olun ya da giriş yapın.

Bu Yazıyı Tutanlar

Bu yazıyı rapor et. Kural dışı içeriğe rastladığınızda editörlerimize rapor ederek müdahale edilmesini sağlayabilirsiniz. (Hangi durumlarda rapor edebilirim?)

Bu site

Nokta ve pilli ortak yapımı olan kodaman.org hep birlikte içerik üretip gelirini yazarları ile paylaştığımız kolektif bir kod yazarları blogudur. Siz de katılabilirsiniz.

pilliilan

son yorumlar

arama

pillinetwork