Студопедия

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

Разделы сайта

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






Класс Thread






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

При программировании на C# поток - это объект класса Thread.

Как обычно, объекты создаются конструктором класса. При создании потоков необходимо задать код, который будет выполняться потоком. Этот код должен быть методом класса. Зачастую, потоку передается не только метод, но и объект, вызывающий метод. Например, в проекте может быть класс Works с методом Work. В клиентском классе, создающем поток, можно создать объект worker класса Work и при создании потока передать ему квалифицированный вызов - worker.Work. Это хороший стиль, облегчающий построение потоко-безопасного приложения, поскольку метод Work будет работать с полями переданного ему объекта, и не будет конфликтовать с другим потоком, работающим с тем же методом Work, но вызванным другим объектом - another_worker.

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

Метод, который будет исполняться потоком, необходимо передать конструктору класса Thread. Поскольку конструктору необходимо передать метод, то соответствующий аргумент конструктора должен иметь функциональный тип и задаваться делегатом, описывающим сигнатуру метода. У класса Thread есть четыре конструктора. Простейший из них имеет один аргумент, тип которого задается делегатом ThreadStart. Этому типу соответствуют все методы, не имеющие аргументов и являющиеся процедурами, - методы типа void M() {…}. Такие методы не являются экзотикой, - они характерны для объектного стиля программирования, когда вся входная и выходная информация метода передается через поля класса.

Если все же методу, выполняемому в потоке, необходимо передать информацию, то можно использовать конструктор класса Thread с одним аргументом, тип которого задается делегатом ParameterizedThreadStart. Этот класс задан следующим образом:

public delegate void ParameterizedThreadStart(Object obj)

Этому типу соответствуют все методы с одним аргументом, являющиеся процедурами. Фактически этот класс является универсальным, позволяющим использовать его для всех методов, имеющих аргументы. Понятно, что предусмотреть все возможные сигнатуры, возникающие в практических задачах, невозможно, поэтому приходится идти на компромисс. Если у метода, передаваемого потоку, один аргумент некоторого типа Т, то он соответствует сигнатуре делегата, поскольку тип object является родителем любого типа. В реализации метода достаточно будет выполнить явное приведение типа object к типу Т. Если же у метода n (n > 1) аргументов, то в этом случае необходимо создать специальный класс (структуру) S_class, описывающий требуемое методу множество аргументов. После этого можно описать метод, передаваемый потоку, как метод с одним аргументом типа S_class, что и позволит передать этот метод конструктору потока.

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

Объявление

Thread my_thread;

позволяет объявить объект, задающий поток. Создать сам объект можно, вызвав конструктор класса Thread:

my_thread = new Thread(my_object.my_method);

передав конструктору метод класса. Все будет синтаксически корректно, если метод my_method не имеет аргументов или имеет один аргумент.

Есть еще один прекрасный способ передать потоку метод с произвольным числом аргументов. Конструктору потока можно передать анонимный метод. Определение анонимного метода может состоять из одной строчки, задающей вызов метода, который и будет выполняться в потоке. В этом случае метод, вызываемый анонимным методом, может иметь произвольную сигнатуру и ему можно передать соответствующий набор фактических аргументов.

Приведу пример, иллюстрирующий рассмотренные способы создания и запуска потоков. Начнем с создания класса Works:

/// < summary>

/// Демо класса, в котором методы работают с полями класса

/// Нет необходимости передавать методу аргументы

/// Методы соответствуют делегату ThreadStart

///

/// < /summary>

class Works

{

string worker;

string job;

string mark;

string res;

public Works(string worker, string job, string mark)

{

this.worker = worker;

this.job = job;

this.mark = mark;

}

public string Res

{

get { return res; }

}

/// < summary>

/// Метод, вызванный объектом класса,

/// может быть передан потоку на выполнение

/// < /summary>

public void Work()

{

res = String.Format(

" Работник {0} выполнил задание: < {1}> с оценкой {2}! ",

worker, job, mark);

}

}

В процедуре Main демонстрируются разные способы создания и запуска трех потоков:

static void Main(string[] args)

{

Thread t = new Thread(delegate() { Info(" Петров", 22); });

// Thread t = new Thread(()=> { Info(" Петров", 22); });

t.Start();

t.Join();

Console.WriteLine(" Подтверждаю, Main");

Works worker1 = new Works(" Петров", " проект с потоками", " отлично");

Works worker2 = new Works(" Сергеев", " интерфейс проекта ", " хорошо");

Thread w1 = new Thread(worker1.Work);

Thread w2 = new Thread(worker2.Work);

w1.Start();

w2.Start();

Console.WriteLine(worker1.Res);

Console.WriteLine(worker2.Res);

}

static void Info(string fio, int age)

{

Console.WriteLine(" Фамилия: " + fio + " Возраст: " + age);

}

}

При создании потока t конструктору передается анонимный метод, представляющий вызов метода Info, которому передаются требуемые аргументы. Заметьте, никаких преобразований аргументов в этом случае не требуется, как и не требуется создания дополнительных классов.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.