Перегрелись
В программе, для синхронизации работы потоков использован метод lock(). Синхронизация потоков рассматривается в следующей главе.
Вопросы:
1. Объектом, какого класса является поток?
2. Чем определяется сигнатура заголовка потоковой функции?
3. Какова последовательность создания потока и запуск его на выполнение?
4. Каким образом можно установить или прочесть имя потока?
5. С помощью какого свойства можно узнать находится ли поток в активном состоянии?
6. Каким образом можно приостановить работу потока на заданное время?
7. С помощью какого метода можно дождаться завершения работы потока?
8. Какие приоритеты потоков могут устанавливаться программно?
9. Какой приоритет потока устанавливается по умолчанию?
10. Какие методы служат для приостановки и возобновления работы потоков?
11. Какой метод служит для аварийного завершения работы потоков?
Пример приложения с потоками
![]() |
Рассмотрим такую простую задачу, как пересчет координат прямолинейно движущихся на поверхности формы объектов с помощью потоков, на примере перемещения окружностей, будем называть их шариками. В момент запуска приложения появляется форма с расположенными на ней шариками (10 штук) и элементами управления, так как это выглядит на рис:
Рис
Затем шарики начинают двигаться вниз под 45 градусов с разными скоростями. Скорости шариков прямо пропорциональны их порядковому номеру. Нумерация шариков по порядку сверху вниз (рис…). Верхний шарик имеет наименьший номер, а нижний наибольший. Шарики движутся в области ограниченной 200 на 200 пикселей, отскакивая от границ области по законам физики (см. рис…). При щелчке на кнопке “Exit”,шарики исчезают с экрана и закрываются связанные с ним потоки. При щелчке на кнопку закрытия окна должно происходить вначале то же самое, что и при щелчке на кнопке “Exit”, а лишь потом закрываться окно. При щелчке на кнопке “Stop”, останавливается шарик, номер которого указан в окне редактора TextBox. Для повышения устойчивости приложения, ввод не числовых данных должен сопровождаться выводом на поверхность редактора сообщения ”Error!!!” (см. рис…).
Рис
![]() |
Для этих целей использовать исключение, возникающее при преобразовании строки символов в число.
![]() |
Рис…
Текст приложения:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsApplication4
{
public partial class Form1: Form
{
int bj;
class Ball
{
int x, y; // координаты
int dx, dy; //приращение координат-определяет скорость
int w, h; //ширина высота шарика
public bool live; // признак жизни
public delegate void DlTp();// Объявление типа (делегат) и
//создание пока что пустой ссылки для организации в последующем
// с помощью ее вызова функции Invalidate()для главного потока
public DlTp dl;
public Thread thr; //Создание ссылки на потоковый объект
// потоковая функция
void FnThr()
{
while (live)
{ //здесь отражемся от границ области
if (x < 0 || x > 200) dx = -dx;
if (y < 0 || y > 200) dy = -dy;
//здесь пересчитываем координаты
x += dx;
y += dy;
Thread.Sleep(100);//спим
dl(); //вызываем с помощью делегата Invalidate()
}
w = h = 0; //схлопываем шарик
dl(); //вызываем с помощью делегата Invalidate()
}
//функция рисования шарика
public void DrawBall(Graphics dc)
{
dc.DrawEllipse(Pens.Magenta, x, y, w, h);
}
//конструктор класса
public Ball(int xn, int yn, int wn, int hn, int dxn, int dyn)
{
x = xn; y = yn; w = wn; h = hn; dx = dxn; dy = dyn;//инициализируем
thr = new Thread(new ThreadStart(FnThr)); //создаем потоковый объект
live = true; //устанавливаем признак жизни
thr.Start(); //запускаем поток
}
}
Ball[] bl = new Ball[10];//массив пустых ссылок типа Ball
public Form1()
{
InitializeComponent();
for (int j = 0; j < bl.Length; j++)
{
//создаем потоковые объекты
bl[j] = new Ball(j, j * 10, 10, 10, j + 1, j + 1);
//подписываемся на событие
bl[j].dl += new Ball.DlTp(Invalidate);
}
}
private void button1_Click(object sender, EventArgs e)
{
for (int j = 0; j < bl.Length; j++)
{
bl[j].live = false;// Уничтожаем потоки
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
for (int j = 0; j < bl.Length; j++)
{
bl[j].live = false;// Уничтожаем потоки
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
for (int j = 0; j < bl.Length; j++)
{
bl[j].DrawBall(e.Graphics);//рисуем
}
}
private void button2_Click(object sender, EventArgs e)
{
try
{// Здесь могет возникнутьисключение
bj = Convert.ToInt32(textBox1.Text);
}
catch
{//Обрабатываем исключение
textBox1.Text = "Error!!!";
return;
}
bl[bj].thr.Suspend();//Останавливаем поток
}
private void button3_Click(object sender, EventArgs e)
{
try
{// Здесь могет возникнутьисключение
bj = Convert.ToInt32(textBox1.Text);
}
catch
{//Обрабатываем исключение
textBox1.Text = "Error!!!";
return;
}
bl[bj].thr.Resume();//возобнавляем работу потока
}
}
}