Сначала создайте новое консольное приложение 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;

}

Обратите внимание на то, что метод Main здесь не вызывает Console.ReadLine, чтобы гарантировать присутствие консоли на экране до нажатия клавиши «Enter». Поэтому при выполнении этого приложения оно сразу же прекратит свою работу, так как объект Thread сконфигурирован для работы в фоновом потоке. С началом работы метода Main создается приоритетный первичный поток, поэтому, как только выполнение программной логики Main завершится, домен приложения будет выгружен, и это произойдет до того, как вторичный поток завершит свою работу. Однако, закомментировав строку, в которой устанавливается свойство IsBackground, вы обнаружите, что на консоль выводятся все числа, поскольку для того, чтобы домен приложения будет выгружен из содержащего его процесса, все приоритетные потоки должны завершить свою работу.

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

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