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

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

Как было сказано, все процессы имеют, по крайней мере, один поток управления, который обычно называется стартовым или основным.

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

  • Он может выполняться.

  • Он может быть готовым к выполнению. Выполняющийся поток может быть приостановлен, т.е. его выполнение временно прекращается. Позже оно может быть возобновлено.

  • Поток может быть заблокирован в ожидании необходимого ресурса.

  • Наконец, поток может завершиться, и уж в этом случае его выполнение окончено и продолжению (возобновлению) не подлежит.

В среде .NET Framework определено два типа потоков: высокоприоритетный (foreground) и низкоприоритетный, или фоновый (background). По умолчанию поток создается высокоприоритетным, но его тип можно изменить, т.е. сделать его фоновым.

Единственное различие между высоко- и низко­приоритетным потоками состоит в том, что последний будет автоматически завершен, если все высокоприоритетные потоки в его процессе остановились.

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

Создание потока

В классе Thread пространства имен System.Threading определен ряд методов и свойств для управления потоками.

Чтобы создать поток, необходимо создать объект типа Thread. В классе Thread определен следующий конструктор:

public Thread ( ThreadStart entryPoint )

Здесь:

Параметр еntryPoint содержит имя метода, который будет вызван, чтобы начать выполнение потока (команд).

Тип ThreadStart — это делегат, определенный в среде .NET Framework:

public delegate void ThreadStart ()

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

Пример:

Thread t2 = new Thread (new ThreadStart (Method) );

Для запуска потока на выполнение необходимо вызвать метод Start(), который определяется в классе Thread:

public void Start()

После выхода из entryPolnt-метода выполнение потока автоматически завершается.

Пример.

t2.Start();

Метод Sleep() приостановливает выполнение потока, из которого он был вызван, на период времени, заданный в миллисекундах.

public static void Sleep ( int milliseconds )

Пример 1. Создание нового потока на базе статического метода

using System;

using System.Threading;

class Class1

{

// Дочерний поток. Метод Coundown считает от 1 до 1000

public static void Method ()

{

for ( int i = 1; i <= 10000; i++)

Console.Write (i + " ");

}

// Стартовый поток

static void Main()

{

// Создание второго потока

// ThreadStart dlg = new ThreadStart(Method));

// Thread t2 = new Thread (dlg );

Thread t2 = new Thread (new ThreadStart (Method) );

// Запуск потока

t2.Start();

// В это же время метод Method вызывается в основном потоке

Method();

Console.ReadLine();

}

}

Пример 2. Создание нового потока на базе динамического метода

using System;

using System.Threading;

class Class1

{

public int count;

private string thrdName;

public Class1(string name)

{

count = 0;

thrdName = name;

}

// Начало (входная точка) потока.

public void Run()

{

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

do

{

Console.Write ("#");

Thread.Sleep(300);

} while (++count < 10);

Console.WriteLine ("\n" + thrdName + " завершен.");

}

}

class MultiThread

{

public static void Main()

{

Console.WriteLine ("Основной поток стартовал.");

// Сначала создаем объект класса Class1.

Class1 mt = new Class1 ("Дочерний поток");

// Затем из метода этого объекта создаем поток.

Thread newThrd = new Thread (new ThreadStart(mt.Run));

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

do

{

Console.Write(".");

Thread.Sleep (200);

} while (mt.count != 10);

Console.WriteLine ("Основной поток завершен.");

}

}

В VS 2005 возможен вызов параметризированного конструктора Thread без делегата. Благодаря такой возможности можно запускать поток, передавая ему параметр в методе Start():

using System;

using System.Threading;

public class Work

{

public static void Main()

{

// To start a thread using a shared thread procedure, use the class name and

// method name when you create the ParameterizedThreadStart delegate.

// C# infers the appropriate delegate creation syntax:

// new ParameterizedThreadStart(Work.DoWork)

Thread newThread = new Thread(Work.DoWork);

// Thread newThread = new Thread(new ParameterizedThreadStart(Work.DoWork));

// Use the overload of the Start method that has a parameter of type Object.

// You can create an object that contains several pieces of data, or you can pass

// any reference type or value type.

// The following code passes the integer value 42.

newThread.Start(42);

// To start a thread using an instance method for the thread

// procedure, use the instance variable and method name when

// you create the ParameterizedThreadStart delegate.

// C# infers the appropriate delegate creation syntax:

// new ParameterizedThreadStart(w.DoMoreWork)

Work w = new Work();

newThread = new Thread(w.DoMoreWork);

// Pass an object containing data for the thread.

newThread.Start("The answer.");

}

public static void DoWork(object data)

{

Console.WriteLine("Static thread procedure. Data='{0}'", data);

}

public void DoMoreWork(object data)

{

Console.WriteLine("Instance thread procedure. Data='{0}'", data);

}

}

/* This code example produces the following output (the order

of the lines might vary):

Static thread procedure. Data='42'

Instance thread procedure. Data='The answer'

*/

Если метод Start содержит параметр, то и вызываемый метод должен быть определен с параметром типа object.