<p>Работа с делегатом ParameterizedThreadStart</p>

Напомним, что делегат ThreadStart может указывать только на методы, возвращающие void и не имеющие аргументов. Во многих случаях этого будет вполне достаточно, но передать данные методу, выполняющемуся во вторичном потоке, вы сможете только с помощью делегата ParameterizedThreadStart. Для примера воссоздадим программную логику проекта AsyncCallbackDelegate, построенного в этой главе выше, но на этот раз используем тип делегата ParameterizedThreadStart.

Сначала создайте новое консольное приложение AddWithThreads и укажите using для пространства имен System.Threading. Поскольку ParameterizedThreadStart может указывать на любой метод, принимающий параметр System.Object, создайте пользовательский тип, содержащий числа для сложения.

class AddParams {

 public int a;

 public int b;

 public AddParams(int numb1, int numb2) {

  a = numb1;

  b = numb2;

 }

}

В классе Program создайте статический метод, который с помощью типа AddParams напечатает сумму соответствующих значений.

public static void Add(object data) {

 if (data is AddParams) {

  Console.WriteLine("ID потока в Add(): {0}", Thread.CurrentThread.GetHashCode());

  AddParams ap = (AddParams)data;

  Console.WriteLine("{0} + {1} равно {2}", ар.a, ар.b, ар.a + ар.b);

 }

}

Программный код Main() в данном случае предельно прост. Просто используйте ParameterizedThreadStart вместо ThreadStart.

static void Main(string[] args) {

 …

 Console.WriteLine("***** Сложение с объектами Thread *****");

 Console.WriteLine("ID потока в Main(): {0}", Thread.CurrentThread.GetHashCode());

 AddParams ap = new AddParams(10, 10);

 Thread t = new Thread(new ParameterizedThreadStart(Add));

 t.Start(ap);

 …

}

Исходный код. Проект AddWithThreads размещен в подкаталоге, соответствующем главе 14.

<p>Приоритетные и фоновые потоки</p>

Итак, вы научились программного создавать новые потоки выполнения с помощью пространства имен System.Threading, теперь давайте выясним, чем отличаются приоритетные и фоновые потоки.

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

Фоновые потоки (иногда называемые демонами) рассматриваются средой CLR, как возобновляемые ветви выполнения, которыми можно пренебречь в любой момент времени (даже при выполнении ими своих задач). Поэтому, когда все приоритетные потоки завершаются, все фоновые потоки будут завершены автоматически в результате выгрузки домена приложения.

Важно понять, что понятия приоритетного и фонового потоков – это не синонимы понятий первичного и рабочего потока. По умолчанию каждый поток, создаваемый с помощью метода Thread.Start(), автоматически оказывается приоритетным потоком. А это значит, что домен приложения не будет выгружен до тех пор, пока в нем все потоки не завершат свою работу. В большинстве случаев это будет именно тем поведением, которое требуется.

Но предположим, что нам нужно вызвать Printer.PrintNumbers() во вторичном потоке, который должен действовать, как фоновый поток. Это означает, что для метода, на который указывает тип Thread (посредством делегата ThreadStart или ParameterizedThreadStart), должна допускаться возможность безболезненного его завершения, как только все приоритетные потоки закончат свою работу. Для настройки такого потока достаточно установить значение true (истина) для свойства IsBackground.

static void Main(string[] args) {

 Printer p = new Printer();

 Thread bgroundThread = new Thread(new ThreadStart(p.PrintNumbers));

  bgroundThread.IsBackground = true;

  bgroundThread.Start();

}

Перейти на страницу:

Похожие книги