Герберт Шилдт - C# 4.0: полное руководство
- Название:C# 4.0: полное руководство
- Автор:
- Жанр:
- Издательство:ООО И.Д. Вильямс
- Год:2011
- Город:Москва -- Киев
- ISBN:978-5-8459-1684-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Герберт Шилдт - C# 4.0: полное руководство краткое содержание
В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки.
Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию
C# 4.0: полное руководство - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Следует, однако, иметь в виду, что метод Dispose()
можно вызывать для отдельной задачи только после ее завершения. Следовательно, для выяснения факта завершения отдельной задачи, прежде чем вызывать метод Dispose()
, потребуется некоторый механизм, например, вызов метода Wait()
. Именно поэтому так важно было рассмотреть метод Wait()
, перед тем как обсуждать метод Dispose()
. Ели же попытаться вызвать Dispose()
для все еще активной задачи, то будет сгенерировано исключение InvalidOperationException
.
Во всех примерах, приведенных в этой главе, создаются довольно короткие задачи, которые сразу же завершаются, и поэтому применение метода Dispose()
в этих примерах не дает никаких преимуществ. (Именно по этой причине вызывать метод Dispose()
в приведенных выше программах не было никакой необходимости. Ведь все они завершались, как только завершалась задача, что в конечном итоге приводило к освобождению от остальных задач.) Но в целях демонстрации возможностей данного метода и во избежание каких-либо недоразумений метод Dispose()
будет вызываться явным образом при непосредственном обращении с экземплярами объектов типа Task
во всех последующих примерах программ. Если вы обнаружите отсутствие вызовов метода Dispose()
в исходном коде, полученном из других источников, то не удивляйтесь этому. Опять же, если программа завершается, как только завершится задача, то вызывать метод Dispose()
нет никакого смысла — разве что в целях демонстрации его применения.
Применение класса TaskFactory для запуска задачи
Приведенные выше примеры программы были составлены не так эффективно, как следовало бы, поскольку задачу можно создать и сразу же начать ее исполнение, вызвав метод StartNew()
, определенный в классе TaskFactory
. В классе TaskFactory
предоставляются различные методы, упрощающие создание задач и управление ими. По умолчанию объект класса TaskFactory
может быть получен из свойства Factory
, доступного только для чтения в классе Task
. Используя это свойство, можно вызвать любые методы класса TaskFactory
. Метод StartNew()
существует во множестве форм. Ниже приведена самая простая форма его объявления:
public Task StartNew(Action action)
где action — точка входа в исполняемую задачу. Сначала в методе StartNew()
автоматически создается экземпляр объекта типа Task
для действия, определяемого параметром action , а затем планируется запуск задачи на исполнение. Следовательно, необходимость в вызове метода Start()
теперь отпадает.
Например, следующий вызов метода StartNew()
в рассматривавшихся ранее программах приведет к созданию и запуску задачи tsk
одним действием.
Task tsk = Task.Factory.StartNew(MyTask);
После этого оператора сразу же начнет выполняться метод MyTask()
.
Метод StartNew()
оказывается более эффективным в тех случаях, когда задача создается и сразу же запускается на исполнение. Поэтому именно такой подход и применяется в последующих примерах программ.
Применение лямбда-выражения в качестве задачи
Кроме использования обычного метода в качестве задачи, существует и другой, более рациональный подход: указать лямбда-выражение как отдельно решаемую задачу. Напомним, что лямбда-выражения являются особой формой анонимных функций. Поэтому они могут исполняться как отдельные задачи. Лямбда-выражения оказываются особенно полезными в тех случаях, когда единственным назначением метода является решение одноразовой задачи. Лямбда-выражения могут составлять отдельную задачу или же вызывать другие методы. Так или иначе, применение лямбда-выражения в качестве задачи может стать привлекательной альтернативой именованному методу.
В приведенном ниже примере программы демонстрируется применение лямбда-выражения в качестве задачи. В этой программе код метода MyTask()
из предыдущих примеров программ преобразуется в лямбда-выражение.
// Применить лямбда-выражение в качестве задачи.
using System;
using System.Threading;
using System.Threading.Tasks;
class DemoLambdaTask {
static void Main() {
Console.WriteLine("Основной поток запущен.");
// Далее лямбда-выражение используется для определения задачи.
Task tsk = Task.Factory.StartNew(() => {
Console.WriteLine("Задача запущена");
for (int count = 0; count < 10; count++) {
Thread.Sleep(500);
Console.WriteLine("Подсчет в задаче равен " + count );
}
Console.WriteLine("Задача завершена");
} );
// Ожидать завершения задачи tsk.
tsk.Wait();
// Освободить задачу tsk.
tsk.Dispose();
Console.WriteLine("Основной поток завершен.");
}
}
Ниже приведен результат выполнения этой программы.
Основной поток запущен.
Задача запущена
Подсчет в задаче равен 0
Подсчет в задаче равен 1
Подсчет в задаче равен 2
Подсчет в задаче равен 3
Подсчет в задаче равен 4
Подсчет в задаче равен 5
Подсчет в задаче равен 6
Подсчет в задаче равен 7
Подсчет в задаче равен 8
Подсчет в задаче равен 9
Задача завершена
Основной поток завершен.
Помимо применения лямбда-выражения для описания задачи, обратите также внимание в данной программе на то, что вызов метода tsk.Dispose()
не делается до тех пор, пока не произойдет возврат из метода tsk.Wait()
. Как пояснялось в предыдущем разделе, метод Dispose()
можно вызывать только по завершении задачи. Для того чтобы убедиться в этом, попробуйте поставить вызов метода tsk.Dispose()
в рассматриваемой здесь программе перед вызовом метода tsk.Wait()
. Вы сразу же заметите, что это приведет к исключительной ситуации.
Создание продолжения задачи
Одной из новаторских и очень удобных особенностей библиотеки TPL является возможность создавать продолжение задачи. Продолжение — это одна задача, которая автоматически начинается после завершения другой задачи. Создать продолжение можно, в частности, с помощью метода ContinueWith()
, определенного в классе Task
. Ниже приведена простейшая форма его объявления:
public Task ContinueWith(Action действие_продолженмя)
где действие_продолжения обозначает задачу, которая будет запущена на исполнение по завершении вызывающей задачи. У делегата Action
имеется единственный параметр типа Task
. Следовательно, вариант делегата Action
, применяемого в данном методе, выглядит следующим образом.
Интервал:
Закладка: