Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методич.указания к заданиям по ТП.doc
Скачиваний:
4
Добавлен:
06.05.2019
Размер:
897.02 Кб
Скачать

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.