Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Многопоточность






Многопоточная программа состоит из двух или более частей, которые могут выполняться одновременно. Каждая часть такой программы называется потоком.

Различают 2 вида многозадачности:

1. с ориентацией на процессы

2. с ориентацией на потоки

Процесс представляет собой выполняемую программу. Поток – это управляемая единица управляемого кода. Все процессы имеют по крайней мере один поток.

Поток может находиться в одном из нескольких состояний:

1. выполнения

2. готов к выполнению

3. приостановлен

4. возобновлен

5. заблокирован в ожидании необходимого ресурса

6. завершен

Классы, которые поддерживают многопоточность, располагаются в пространстве имён System.Threading.

Алгоритм создания вторичных потоков:

Шаг 1: создать метод, который будет точкой входа для нового потока.

Шаг 2: создать новый делегат ThreadStart или ParametrizedThreadStart, передав конструктору метод, определённый на шаге 1.

Шаг 3: создать объект класса Thread и передать в качестве аргумента конструктора делегат из шага 2.

Шаг 4: установить начальные характеристики потока (имя и т.д.).

Шаг 5: вызвать метод Thread.Start(), который запустит поток на методе, который указан делегатом в пункте 2.

Листинг 9.1 Пример создания многопоточного приложения

using Sustem.Threading;

class Printer

{

public void PrintNum()

{

Console.Write(Thread.CurienEThread.Name);

for (int i = 0; i < 10; i++)

{

Console.Write(“i=”+i);

Thread.Step(500);

}

}

}

class Test

{

public static void Main()

{

Thread PrimTh = Thread.CurrentThread;

PrinTh.Name = “First”;

Console.Write(PrinTh.Name);

Printer P = new Printer;

Thread SecondTh = new Thread

(new ThreadStart(p.printName))

SecondTh.Name = “Second”;

SecondTh.Start();

for (int j = 10; j < 20; j++)

Cionsole.Write(“j=”, j);

return 0;

}

}

В программе можно создавать несколько потоков.

В классе Thread предусмотрено два средства, которые позволяют установить факт завершения выполнения потока:

1. Свойство isAlive возвращает значение true, если поток, для которого оно вызвано, ещё выполняется, в противном случае false.

2. Метод Join () ожидает, пока поток, для которого он был вызван, не завершится.

Существует два типа потоков:

1. Высокоприоритетные потоки (потоки высокого плана)

2. Низкоприоритетные потоки (фоновые)

Различия между типами потоков заключаются в том, что фоновые потоки автоматически завершаются, если завершён поток переднего плана. По умолчанию, каждый поток автоматически становится потоком переднего плана.

Чтобы сделать поток фоновым, необходимо установить его свойство IsBackGround в true.

При использовании в программе нескольких потоков иногда необходимо координировать их выполнение. Процесс координации потоков называется синхронизацией. К синхронизации прибегают в тех случаях, когда двум или большему числу потоков необходимо получить доступ к общему ресурсу, который в каждый момент времени может использовать только один поток.

В основе синхронизации лежит понятие блокировки, т.е. управления доступом к некоторому блоку кода в объекте. На то время, когда объект заблокирован одним потоком, никакой другой поток не может получить доступ к заблокированному блоку кода.

Одним из способов поддержки синхронизации является использование ключевого слова lock. Ключевое слово lock позволяет определять контекст операторов, которые должны быть синхронизированы между потоками. Lock требует указания маркера, т.е. ссылки на объект.

Как только поток войдёт в контекст lock маркер блокировки станет недоступным другим потокам до тех пор, пока блокировка не будет снята при выходе из контекста lock.

Каждый поток имеет определённый приоритет. Приоритет потока определяет, какой объём процессорного времени получает поток. По умолчанию все потоки имеют уровень приоритета normal. Уровни приоритетов хранятся в перечислении Thread.Priority. Пример использования: SecondTh.Priority = AboveNormal.

Для приостановки потока используется метод Thread.Suspend(). Для возобновления – Thread.Resume(). Для завершения – Thread.Abort().

Состояние потока можно получить из свойства Thread.State.

В многозадачной среде ориентированной на процессы вместо запуска в той же программе ещё одного потока, одна программа запускает на выполнение другую программу. В C# это реализуется с использованием класса Process из пространства имён System.Diagnostics. Для запуска программы используется метод Start(string name), в который передаётся имя программы. Для завершения программы используется метод Close().

Листинг 9.2. Демонстрация синхронизации посредством управления доступом к методу sumIt(), который суммирует элементы массива целочисленного типа:

// Использование инструкции lock для синхронизации

// доступа к объекту.

using System;

using System.Threading;

class SumArray

{

int sum;

public int sumlt(int[] nums)

{

lock(this)

{ // Блокировка всего метода,

sum =0; // Начальное значение суммы.

for(int i=0; i < nums.Length; i++)

{

sum += nums[i];

Console.WriteLine(" Промежуточная сумма для потока " + Thread.CurrentThread.Name +

" равна " + sum);

Thread.Sleep(10); // Разрешено переключение задач.

}

return sum;

}

}

}

class MyThread

{

public Thread thrd;

int [] a;

int answer;

/* Создаем один объект класса SumArray для всех

экземпляров класса MyThread. */

static SumArray sa = new SumArray (*);

// Создаем новый поток.

public MyThread(string name, int[] nums)

{

a = nums;

thrd = new Thread(new ThreadStart(this.run));

thrd.Name = name;

thrd.Start(); // Запускаем поток на выполнение.

}

// Начало выполнения нового потока,

void run()

{

Console.WriteLine(thrd.Name + " стартовал.");

answer = sa.sumIt(a);

Console.WriteLine(" Сумма для потока " + thrd.Name +

" равна " + answer);

Console.WriteLine(thrd.Name + " завершен.");

}

}

 

class Sync

{

public static void Main()

{

int[] a - {1, 2, 3, 4, 5};

MyThread mtl = new MyThread(" Потомок #1", a);

MyThread mt2 = new MyThread(" Потомок #2", a);

mtl.thrd.Join();

mt2.thrd.Join();

}

}

Листинг 9.3 Напишите программу реализующую создание второго потока при ее запуске и обмен данными между потоками.

using System;

using System.Threading;

 

namespace LabTh

{

class Program

{

static bool stopThread;

public static void MyThread()

{

for (int i = 0;; i++)

{

if (stopThread)

break;

Console.WriteLine(" MyThread: {0}", i);

 

Thread.Sleep(2000);

}

Console.WriteLine(" Поток MyThread остановлен");

}

[STAThread]

static void Main(string[] args)

{

ThreadStart myThreadDelegate = new ThreadStart(MyThread);

Thread thr = new Thread(myThreadDelegate);

Console.WriteLine(" Запуск потока MyThread");

stopThread = false;

thr.Start();

string str;

do

{

Console.WriteLine(" Команда (х -- выход): ");

str = Console.ReadLine();

Console.WriteLine(" основной поток: {0}", str);

}

while (str! = " x");

stopThread = true;

Console.ReadLine();

}

}

}

 


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.014 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал