Vo formulári sú umiestnené dve tlačidlá s popisom "Start thread 1" a "Start thread 1". Po stlačení každého sa naštartuje jedno vlákno, ktoré inkrementuje svoju vlastnú premennú "i1" a "i2". Zmenu hodnoty možno ihneď pozorovať v labeloch pod každým tlačidlom. Zastavovať a rozbehnúť je možné každé vlákno zvlášť tlačidlami "Stop thread 1" a "Stop thread 2". Aplikácia je v princípe jednoduchá, ide iba o najľahšiu demonštráciu/ukážku práce s vláknami pre programátora. Detailný popis jednotlivého kódu je na dlhšie. V princípe napoviem iba, že využívam v tomto prípade tzv. "callback" funkciu, ktorá spustí asynchrónne napr. SetText1 funkciu pretože nastavenie mnohých vizuálnych vlastností objektov sa vykonáva pomocou tzv. messages - správ, kôli synchronizácii poradia prekreslenia jednotlivých objektov. Aby mohlo takéto vlákno bezpečne nastavovať inkrementovanú hodnotu vo vlastnosti text objektu label. Ďalej stojí za povšimnutie v zdrojovom kóde v metóde DoThread1() použitie statickej metódy triedy vlákna Thread.Sleep(1), ktorou dovolíme na 1 milisekundu urobiť niečo aj ostatným vláknam a premenné "private volatile bool Thread1Running" a "private volatile bool Thread2Running" sú označené kľúčovým slovom "volatile", kde povieme, že chceme, aby mohlo k nim pristupovať viac vlákien. V tomto prípade primárne a ďalšie, nami naštartované tlačidlom. Premenné Thread1Running a Thread2Running používam na kontrolu chodu vlákien - zastavenie.
Po vytvorení oknovej aplikácie si pomenujte a nastavte nasledovné vlastnosti v programe takto:
Assembly name: Threads
Default namespace: Threads
Target framework: .NET Framework 4 Client Profile
Output type: Windows Application
Takže vytvoril som si jednoduchý formulár s menom "Threadform" s ďalšími objektami.
Object: form Name: Threadform Text: Threads
Tlačidlá na štart vlákien:
Object: button Name: button1 Text: Start thread 1
Object: button Name: button2 Text: Start thread 2
Labely/texty na zobrazenie behu vlákien:
Object: label Name: label_thread1 Text: 0
Object: label Name: label_thread2 Text: 0
Tlačidlá na ukončenie vlákien:
Object: button Name: button3 Text: Stop thread 1
Object: button Name: button4 Text: Stop thread 2
Tieto objekty si rozmiestnite na formulári do riadku v poradí:
button1 - button2
label_thread1 - label_thread2
button3 - button4
Kód v c#:
using System;
//using System.Collections.Generic;
//using System.ComponentModel;
//using System.Data;
//using System.Drawing;
//using System.Linq;
//using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Threads
{
public partial class Threadform : Form
{
private int i1 = 0;
private int i2 = 0;
private volatile bool Thread1Running = false;
private volatile bool Thread2Running = false;
private Thread Thread1;
private Thread Thread2;
delegate void SetTextCallback1(string text);
delegate void SetTextCallback2(string text);
public Threadform()
{
InitializeComponent();
}
private void StartThread1()
{
if (this.Thread1 == null)
{
this.Thread1Running = true;
this.Thread1 = new Thread(new ThreadStart(this.DoThread1));
this.Thread1.Name = "Thread1";
this.Thread1.Priority = ThreadPriority.BelowNormal;
this.Thread1.Start();
}
}
private void EndThread1()
{
this.Thread1Running = false;
if (this.Thread1 != null)
{
this.Thread1.Abort();
this.Thread1 = null;
}
}
private void StartThread2()
{
if (this.Thread2 == null)
{
this.Thread2Running = true;
this.Thread2 = new Thread(new ThreadStart(this.DoThread2));
this.Thread2.Name = "Thread2";
this.Thread2.Priority = ThreadPriority.BelowNormal;
this.Thread2.Start();
}
}
private void EndThread2()
{
this.Thread2Running = false;
if (this.Thread2 != null)
{
this.Thread2.Abort();
this.Thread2 = null;
}
}
private void DoThread1()
{
while (this.Thread1Running)
{
this.SetText1("Value: " + this.i1.ToString());
this.i1++;
Thread.Sleep(1);
}
this.SetText1("Thread finished: " + this.i1.ToString());
}
private void DoThread2()
{
while (this.Thread2Running)
{
this.SetText2("Value: " + this.i2.ToString());
this.i2++;
Thread.Sleep(1);
}
this.SetText2("Thread finished: " + this.i2.ToString());
}
private void SetText1(string text)
{
if (this.Thread1Running && this.Thread1 != null)
{
if (this.label_thread1.InvokeRequired)
{
SetTextCallback1 d1 = new SetTextCallback1(this.SetText1);
this.label_thread1.Invoke(d1, new object[] { text });
}
else
{
label_thread1.Text = text;
}
}
}
private void SetText2(string text)
{
if (this.Thread2Running && this.Thread2 != null)
{
if (this.label_thread2.InvokeRequired)
{
SetTextCallback2 d2 = new SetTextCallback2(this.SetText2);
this.label_thread2.Invoke(d2, new object[] { text });
}
else
{
label_thread2.Text = text;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
StartThread1();
this.button1.Text = "Running thread 1";
this.button3.Enabled = !(this.button1.Enabled = false);
}
private void button2_Click(object sender, EventArgs e)
{
StartThread2();
this.button2.Text = "Running thread 2";
this.button4.Enabled = !(this.button2.Enabled = false);
}
private void button3_Click(object sender, EventArgs e)
{
this.EndThread1();
this.button1.Text = "Start thread 1";
this.button3.Enabled = !(this.button1.Enabled = true);
}
private void button4_Click(object sender, EventArgs e)
{
this.EndThread2();
this.button2.Text = "Start thread 2";
this.button4.Enabled = !(this.button2.Enabled = true);
}
}
}
Zdrojové súbory sú k dispozícii v prílohe. Aplikáciu preložte (build) a spustite a môžete si skúsť, ako samostatne a nezávisle pracujú vlákna a vy môžete hýbať a pracovať nezávisle s formulárom.
Program bol navrhnutý v prostredí: Microsoft Visual Studio 2010 Ultimate, Microsoft .NET Framework Version 4.0.30319 SP1Rel
Predpokladám základné znalosti s prácou objektami a prácou vo Visual C#.
S pozdravom.
AB







