***** Working with Timer type *****
Hit key to terminate...
Time is: 6:51:48 PM
Time is: 6:51:49 PM
Time is: 6:51:50 PM
Time is: 6:51:51 PM
Time is: 6:51:52 PM
Press any key to continue ...
Чтобы передать целевому методу делегата какую-то информацию, необходимо просто заменить значение null во втором параметре конструктора подходящей информацией, например:
// Установить параметры таймера.
Timer t = new Timer(timeCB, "Hello From C# 9.0", 0, 1000);
You can then obtain the incoming data as follows:static void PrintTime(object state)
{
Console.WriteLine("Time is: {0}, Param is: {1}",
DateTime.Now.ToLongTimeString(), state.ToString());
}
Использование автономного отбрасывания (нововведение в версии 7.0)
В предыдущем примере переменная Timer не применяется в каком-либо пути выполнения и потому может быть заменена отбрасыванием:
var _ = new Timer(
timeCB, // Объект делегата TimerCallback.
null, // Информация для передачи в вызванный метод
// (null, если информация отсутствует).
0, // Период ожидания перед запуском
// (в миллисекундах).
1000); // Интервал между вызовами
// (в миллисекундах).
Класс ThreadPool
Следующей темой о потоках, которую мы рассмотрим в настоящей главе, будет роль пула потоков. Запуск нового потока связан с затратами, поэтому в целях повышения эффективности пул потоков удерживает созданные (но неактивные) потоки до тех пор, пока они не понадобятся. Для взаимодействия с этим пулом ожидающих потоков в пространстве имен System.Threading предлагается класс ThreadPool.
Чтобы запросить поток из пула для обработки вызова метода, можно использовать метод ThreadPool.QueueUserWorkItem(). Он имеет перегруженную версию, которая позволяет в дополнение к экземпляру делегата WaitCallback указывать необязательный параметр System.Object для передачи специальных данных состояния:
public static class ThreadPool
{
...
public static bool QueueUserWorkItem(WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callBack,
object state);
}
Делегат WaitCallback может указывать на любой метод, который принимает в качестве единственного параметра экземпляр System.Object (представляющий необязательные данные состояния) и ничего не возвращает. Обратите внимание, что если при вызове QueueUserWorkItem() не задается экземпляр System.Object, то среда .NET Core Runtime автоматически передает значение null. Чтобы продемонстрировать работу методов очередей, работающих с пулом потоков .NET Core Runtime, рассмотрим еще раз программу (в проекте консольного приложения по имени ThreadPoolApp), в которой применяется тип Printer. На этот раз массив объектов Thread не создается вручную, а метод PrintNumbers() будет назначаться членам пула потоков:
using System;
using System.Threading;
using ThreadPoolApp;
Console.WriteLine("***** Fun with the .NET Core Runtime Thread Pool *****\n");
Console.WriteLine("Main thread started. ThreadID = {0}",
Thread.CurrentThread.ManagedThreadId);
Printer p = new Printer();
WaitCallback workItem = new WaitCallback(PrintTheNumbers);
// Поставить в очередь метод десять раз.
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(workItem, p);
}
Console.WriteLine("All tasks queued");
Console.ReadLine();
static void PrintTheNumbers(object state)
{
Printer task = (Printer)state;
task.PrintNumbers();
}