- •Введение к заданиям Основные термины, используемые в дисциплинах
- •Объекты, классы и язык uml
- •Цели задачи заданий
- •Требования к выполнению заданий
- •Оформление результатов
- •4. Содержание разделов пояснительной записки
- •5. Оформление результатов
- •Список литературы
- •Приложение 1. Пример оформления результатов
- •Содержание
- •5.1. Первый этап. Разработка компонента Warehouse
- •5.2. Второй этап. Разработка компонентов ContrlRegion и Lorry
- •5.3. Третий этап. Разработка приложения csLorryAndWarehouse
- •1. Задание
- •Уточнение задания
- •3. Описание разрабатываемой программы с точки зрения пользователя
- •4. Описание разрабатываемой программы с точки зрения программиста
- •4.1. Объектное представление программы
- •4.2. События, потоки и ресурсы
- •5. Поэтапная разработка программы
- •5.1. Первый этап. Разработка компонента Warehouse
- •5.2. Второй этап. Разработка компонентов ContrlRegion и Lorry
- •5.3. Третий этап. Разработка приложения csLorryAndWarehouse
- •6. Описание проблем, возникших при разработке программной системы.
- •7. Список используемой литературы
- •10. Разработка многокомпонентной программы с удалённым объектом
- •10.1. Удалённый компонент RemObj
- •10.2. Сервер csLorryAndWarhousesServer
- •10.3. Клиент csLorryAndWarhousesClient
5.2. Второй этап. Разработка компонентов ContrlRegion и Lorry
Объектами компонента Lorry являются грузовики, перевозящие груз из склада в склад. Компонент Lorry содержит поток, учитывающий все особенности поведения грузовика: из одного склада загружается груз, затем грузовик перемещается к другому складу и, встретив зону контроля, приостанавливается на некоторое случайное время, дабы обследоваться на исправность и выполнить, при необходимости, ремонт, потом грузовик подъезжает к складу и встаёт в очередь, если подлежат разгрузке или погрузке другие грузовики, и, наконец, разгружается. К потокам грузовиков, выполняющим все эти действия, применяется механизм синхронизации на этапах загрузки и выгрузки, а также и при прохождении зоны контроля.
Разделяемый ресурс является объектом компонента ContrlRegion. Чтобы упростить представление этого разделяемого ресурса – зоны контроля – в прикладном окне, наследуем компонент ContrlRegion из класса UserControl, а для ограничения доступа к нему объектов компонента Lorry (грузовиков) создадим в нём объект мютекса. Пусть свойство Semaphore возвращает ссылку на мютекс, которой воспользуется каждый объект компонента Lorry.
Компонент ContrlRegion прост. Его диаграмма классов иа сам компонент представлены ниже. Компонент ContrlRegion размещён в библиотеке csContrlRegion с пространством имён csContrlRegionDll.
Рис. Диаграмма классов компонента ContrlRegion
Компонент csContrlRegion.
///////////////
// C#
using System;
using System.Threading;
using System.Windows.Forms;
namespace csContrlRegionDll
{
// Компонент ContrlRegion
public class ContrlRegion: UserControl
{ Mutex mutex; // Ссылка на объект мютекса
// Конструктор
public ContrlRegion ( )
{mutex= new Mutex ( ); }
// Свойство Semaphore
public Mutex Semaphore
{get {return mutex;}}
}
}
Рис. Диаграмма классов компонента Lorry
Компонент csLorry.
///////////////
// C#
using System;
using System.Threading;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using csWarehouseDll;
using csContrlRegionDll;
namespace csLorryDll
{
// Компонент Lorry
public class Lorry : Component
{ int number; // Номер объекта компонента
Point p; // Координаты объекта компонента
int dX; // Приращение координаты Х
bool leftRight; // Направление перемещения груза
ContrlRegion region; // Ссылка на зону контроля
bool inContrl; // Признак нахождения в зоне контроля
Random rand; // Ссылка на объект случайного числа
bool life; // Признак жизни потока
bool run; // Признак выполнения потока
Thread thr; // Ссылка на объект потока
int timePeriod= 100; // Временной интервал перемещения
Warehouse leftWH; // Ссылка на левый склад
Warehouse rightWH; // Ссылка на правый склад
// Конструктор
public Lorry (int Number, int Y, int DX, Warehouse LeftWH,
Warehouse RightWH, ContrlRegion Region)
{
number= Number; dX= DX; leftRight= true; life= false;
run= false; leftWH= LeftWH; rightWH= RightWH;
region= Region; inContrl= false; p= new Point ( );
p.X= leftWH.Location.X+leftWH.Width + 1; p.Y= Y;
rand= new Random ( );
// Создать объект потока
thr= new Thread (new ThreadStart (Moving));
}
// Свойство Number
public int Number {get {return number;}}
// Свойство Point
public Point Point {get {return p;}}
// Свойство LeftRight
public bool LeftRight
{
set {leftRight= value;}
get {return leftRight;}
}
// Стартовать поток
public void Start ( )
{
life= true; run= true;
thr.Start ( );
}
// Завершить поток
public void Finish ( ) {life= false; thr.Join ( );}
// Приостановить поток
public void Stop ( )
{
if (run)
{ run= false;
thr.Suspend ( );
}
}
// Возобновить поток
public void Run ( )
{
if (!run)
{ run= true;
thr.Resume ( );
}
}
// Потоковая функция компонента
private void Moving ( )
{
while (life)
{ // Объект компонента достиг справа
// объекта левого склада
if (p.X <= leftWH.Location.X+leftWH.Width)
{
Console.WriteLine ("Левая граница");
if (leftRight) // Пересылка слева направо
leftWH.Get ( ); // Загрузить груз
else
leftWH.Put ( ); // Выгрузить груз
dX= -dX;
}
// Объект компонента достиг слева
// объекта правого склада
if (p.X >= rightWH.Location.X)
{
Console.WriteLine ("Правая граница");
if (leftRight) // Пересылка слева направо
rightWH.Put ( ); // Выгрузить груз
else
rightWH.Get ( ); // Загрузить груз
dX= -dX;
}
// Обслужить в зоне контроля
Point pR= new Point (region.Location.X,
region.Location.Y);
Rectangle rect= new Rectangle (pR.X, pR.Y, region.Width,
region.Height);
// Вошли в зону контроля
if (rect.Contains (p) && !inContrl) // Вошли в зону
{
Console.WriteLine ("Вошли в зону");
inContrl= true;
// Захватить разделяемый ресурс
region.Semaphore.WaitOne ( );
Thread.Sleep (rand.Next (100, 300));
}
if (!rect.Contains (p) && inContrl) // Вышли из зоны
{
Console.WriteLine ("Вышли из зоны");
inContrl= false;
// Освободить разделяемый ресурс
region.Semaphore.ReleaseMutex ( ); }
Thread.Sleep (timePeriod);
p.X += dX;
}
}
}
}
Приложение csTestLorry.
///////////////
// C#
using System;
using System.Threading;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using csWarehouseDll;
using csContrlRegionDll;
using csLorryDll;
namespace csTestLorry
{
class TestLorry: Form
{
Warehouse leftWH; // Ссылки на объект левого склада
Warehouse rightWH; // Ссылки на объект правого склада
Lorry lorry1, lorry2; // Ссылки на объекты грузовиков
ContrlRegion region; // Ссылка на объект зоны контроля
bool leftRight; // Признак направления перемещения грузовиков
bool life; // Признак жизни потока управления загрузкой
// и выгрузкой складов
Thread thr; // Ссылка на поток управления загрузкой
// и выгрузкой складов
public TestLorry ( )
{
// Создать объект левого склада
leftWH= new Warehouse (true, true);
leftWH.Location= new Point (10, 10);
leftWH.Size= new Size (30, 100);
leftWH.BackColor= Color.White;
leftWH.evFromWarehouse+=
new DelEvFromWarehouse (WarehouseHandler);
this.Controls.Add (leftWH);
leftWH.Show ( );
// Создать объект правого склада
rightWH= new Warehouse (false, false);
rightWH.Location= new Point (200, 10);
rightWH.Size= new Size (30, 100);
rightWH.BackColor= Color.White;
rightWH.evFromWarehouse+=
new DelEvFromWarehouse (WarehouseHandler);
this.Controls.Add (rightWH);
rightWH.Show ( );
// Создать область контроля
region= new ContrlRegion ( );
region.Location= new Point (100, 0);
region.Size= new Size (40, ClientSize.Height);
region.BackColor= Color.LightSkyBlue;
this.Controls.Add (region);
region.Show ( );
// Задать начальное движение грузовиков слева направо
leftRight= true;
// Создать первый объект грузовика
lorry1= new Lorry (1, 10, 10, leftWH, rightWH, region);
lorry1.Start ( );
// Создать второй объект грузовика
lorry2= new Lorry (2, 40, 20, leftWH, rightWH, region);
lorry2.Start ( );
// Создать и запустить поток управления загрузкой
// и выгрузкой складов
life= true;
thr= new Thread (new ThreadStart (Go));
thr.Start ( );
}
// Обработать событие evFromWarehouse
void WarehouseHandler (object ob, WarehouseEventArgs arg)
{
// Выдать информацию о направлении перемещения грузо-
// виков и о складе, объект которого сгенерировал событие
Console.Write("event evFromWarehouse leftRight=" +
leftRight);
if (arg.Left)
Console.Write (" Компонент leftWH ");
else Console.Write (" Компонент rightWH ");
if (arg.Full)
Console.WriteLine(" полный");
else Console.WriteLine(" пустой");
Console.WriteLine( );
// Изменить направление перемещения грузовиков
if( (arg.Left && arg.Full)||
(!arg.Left && !arg.Full))
leftRight= true;
if ((arg.Left && !arg.Full)||
(!arg.Left && arg.Full))
leftRight= false;
// Указать направление грузовикам
lorry1.LeftRight= leftRight;
lorry2.LeftRight= leftRight;
}
// Обеспечить загрузку груза в склады и
// выгрузку груза из складов
void Go ( )
{
while (life)
{
Invalidate ( );
Thread.Sleep (50);
}
}
// Завершить поток управления загрузкой
// и выгрузкой складов
void Finish()
{
life= false;
thr.Join ( );
lorry1.Finish ( );
lorry2.Finish ( );
}
// Завершить все потоки при закрытии прикладного окна
protected override void OnClosed (EventArgs e)
{
base.OnClosed (e);
Finish ( );
}
// Перерисовать область клиента прикладного окна
protected override void OnPaint (PaintEventArgs e)
{
base.OnPaint (e);
e.Graphics.DrawEllipse (new Pen (Color.Blue, 2),
lorry1.Point.X - 10, lorry1.Point.Y - 10, 20, 20);
e.Graphics.DrawString (lorry1. Number.ToString ( ), Font,
new SolidBrush (Color.Red), lorry1.Point.X - 3,
lorry1.Point.Y- 4);
e.Graphics.DrawEllipse (new Pen (Color.Blue, 2),
lorry2.Point.X - 10, lorry2.Point.Y - 10, 20, 20);
e.Graphics.DrawString (lorry2.Number.ToString ( ), Font,
new SolidBrush (Color.Red), lorry2.Point.X - 3,
lorry2.Point.Y - 4); }
static void Main ( )
{
// Создать объект прикладного окна
TestLorry testLorry= new TestLorry ( );
// Запустить приложение с прикладным окном
Application.Run (testLorry);
}
}
}
Рис. Прикладное и консольное окна программы csTestLorry.