- •Учебное пособие по дисциплине «программирование»
- •Оглавление
- •1 С# 6.0 и платформа .Net 4.6 6
- •С# 6.0 и платформа .Net 4.6
- •Платформа Microsoft .Net Framework.
- •Понятия приложения, проекта, решения
- •Среда разработки Visual Studio .Net
- •Создание первого проекта
- •Компиляция и выполнение программы в среде clr
- •Технология объектно-ориентированного программирования
- •Состав языка
- •Типы данных
- •Переменные и константы
- •Организация ввода-вывода данных. Форматирование.
- •Вывод данных
- •Ввод данных
- •Операции
- •3. Отрицание:
- •9. Условная операция.
- •Выражения и преобразование типов
- •Операторы языка c#
- •Операторы следования
- •Операторы ветвления
- •Оператор выбора switch
- •Операторы цикла
- •Операторы безусловного перехода
- •Методы: основные понятия
- •Необязательные параметры
- •Именованные параметры
- •Перегрузка методов
- •Рекурсивные методы
- •Обработка исключений
- •Оператор try
- •Операторы checked и unchecked
- •Генерация собственных исключений
- •Полезные совет
- •Массивы
- •Одномерные массивы
- •Многомерные массивы
- •Ступенчатые массивы
- •Оператор foreach и его использование при работе с массивами
- •Символы и строки
- •Символы char
- •Неизменяемые строки string
- •Изменяемые строки
- •Регулярные выражения
- •Метасимволы в регулярных выражениях
- •Поиск в тексте по шаблону
- •Редактирование текста
- •Организация с#-системы ввода-вывода
- •Байтовый поток
- •Символьный поток
- •Двоичные потоки
- •Перенаправление стандартных потоков
- •Работа с файловой системой
- •Работа с каталогами Абстрактный класс FileSystemInfo
- •Класс DirectoryInfo
- •Класс Directory
- •Работа с файлами Класс Filelnfo
- •Класс File
- •Основные понятия
- •Данные: поля и константы
- •Конструкторы
- •Конструкторы экземпляра
- •Конструкторы класса
- •Свойства
- •«Один класс – один файл»,
- •Классы (продолжение)
- •Деструкторы
- •Индексаторы
- •Операции класса
- •Унарные операции
- •Бинарные операции
- •Операции преобразования типов
- •Иерархия классов
- •Наследование
- •Использование защищенного доступа
- •Наследование конструкторов
- •1) Позволяет вызвать конструктор базового класса:
- •2) Позволяет получить доступ к члену базового класса, который скрыт "за" членом производного класса.
- •Многоуровневая иерархия
- •Переменные базового класса и производного класса
- •Виртуальные методы
- •Абстрактные методы и классы
- •Запрет наследования
- •Обобщенные типы
- •Значения по умолчанию
- •Статические поля обобщенных классов
- •Ограничения универсальных типов
- •Использование нескольких универсальных параметров
- •Обобщенные методы
- •Наследование обобщенных типов
- •Анонимные типы
- •Методы расширения
- •Интерфейсы
- •Введение в интерфейсы
- •Интерфейсы в преобразованиях типов
- •Обобщенные интерфейсы
- •Явное применение интерфейсов
- •Клонирование объектов. Интерфейс iCloneable
- •Сортировка объектов. Интерфейс iComparable
- •Применение компаратора
- •Ковариантность и контравариантность обобщенных интерфейсов
- •Структуры
- •Перечисления enum
- •Коллекции
- •Введение в коллекции
- •Необобщенные коллекции
- •Обобщенные коллекции
- •Инициализация словарей
- •Класс ObservableCollection
- •Индексаторы и создание коллекций
- •Интерфейсы iEnumerable и iEnumerator
- •Итераторы и оператор yield
- •Именованный итератор
- •Класс Hashtable
- •Делегаты, события и лямбды
- •Делегаты
- •События
- •Класс данных события AccountEventArgs
- •Анонимные методы
- •Ковариантность и контравариантность делегатов
- •Ковариантность и контравариантность в обобщенных делегатах
- •Делегаты Action, Predicate и Func
- •Встроенные Методы (Expression–Bodied)
- •Сериализация
- •Введение в сериализацию объектов
- •Атрибут Serializable
- •Формат сериализации
- •Бинарная сериализация. BinaryFormatter
- •Сериализация в формат soap. SoapFormatter
- •Сериализация в xml. XmlSerializer
- •Сериализация в json. DataContractJsonSerializer
- •Сборка мусора, управление памятью и указатели
- •Сборщик мусора в c#
- •Класс System.Gc
- •Финализируемые объекты
- •Создание деструкторов
- •Интерфейс iDisposable
- •Комбинирование подходов
- •Общие рекомендации по использованию Finalize и Dispose
- •Указатели
- •Ключевое слово unsafe
- •Операции * и &
- •Получение адреса
- •Операции с указателями
- •Указатель на другой указатель
- •Указатели на структуры, члены классов и массивы
- •Указатели на массивы и stackaloc
- •Оператор fixed и закрепление указателей
- •Dlr в c#. Ключевое слово dynamic
- •Сборки .Net
- •Роль сборок в приложениях .Net
- •Манифест сборки
- •Атрибуты сборки
- •Разделяемые сборки. Добавление сборки в gac
- •Строгое имя сборки
- •Многопоточность
- •Введение в многопоточность. Класс Thread
- •Получение информации о потоке
- •Статус потока
- •Приоритеты потоков
- •Создание потоков. Делегат ThreadStart
- •Потоки с параметрами и ParameterizedThreadStart
- •Синхронизация потоков
- •Мониторы
- •Класс AutoResetEvent
- •Мьютексы
- •Семафоры
- •Использование таймеров
- •Параллельное программирование и библиотека tpl
- •Задачи и класс Task
- •Массив задач
- •Работа с классом Task
- •Свойства класса Task
- •Возвращение результатов из задач
- •Задачи продолжения
- •Класс Parallel
- •Выход из цикла
- •Отмена задач и параллельных операций. CancellationToken
- •Отмена параллельных операций Parallel
- •Aсинхронное программирование
- •Асинхронные делегаты
- •IAsyncResult и методы BeginInvoke/EndInvoke
- •Асинхронные методы, async и await
- •Последовательный и параллельный вызов асинхронных методов
- •Обработка ошибок в асинхронных методах
- •Обработка исключений в async void-методах
- •Обработка нескольких исключений. WhenAll
- •Await в блоках catch и finally
- •Отмена асинхронных операций
- •Рефлексия
- •Введение в рефлексию. Класс System.Type
- •Получение типа
- •Применение рефлексии и исследование типов
- •Получение информации о методах
- •Получение конструкторов
- •Получение информации о полях и свойствах
- •Поиск реализованных интерфейсов
- •Динамическая загрузка сборок и позднее связывание
- •Позднее связывание
- •Атрибуты в .Net
- •Ограничение применения атрибута
- •Основы linq
- •Методы расширения linq
- •Список используемых методов расширения linq
- •Фильтрация выборки и проекция
- •Фильтрация
- •Выборка сложных объектов
- •Сложные фильтры
- •Проекция
- •Переменые в запросах и оператор let
- •Выборка из нескольких источников
- •Сортировка
- •Множественные критерии сортировки
- •Работа с множествами
- •Разность множеств
- •Пересечение множеств
- •Объединение множеств
- •Удаление дубликатов
- •Агрегатные операции
- •Метод Aggregate
- •Получение размера выборки. Метод Count
- •Получение суммы
- •Максимальное, минимальное и среднее значения
- •Методы Skip и Take
- •Группировка
- •Соединение коллекций. Метод Join, GroupJoin и Zip
- •Метод Zip
- •Методы All и Any
- •Отложенное и немедленное выполнение linq
- •Делегаты и анонимные методы в запросах linq
- •Работа с xml в c#
- •Работа с xml с помощью классов System.Xml
- •Изменение xml-документа
- •Удаление узлов
- •Linq to Xml. Создание Xml-документа
- •Выборка элементов в linq to xml
- •Изменение документа в linq to xml
- •Введение в Parallel linq. Метод AsParallel
- •Метод AsParallel
- •Метод ForAll
- •Метод AsOrdered
- •Обработка ошибок и отмена операции
- •Прерывание параллельной операции
- •Службы Windows
- •Создание службы для Windows
- •Установка службы
- •Сетевое программирование в с# и .Net
- •Основы работы с сетями в c# и .Net
- •Введение в сети и протоколы
- •Адреса в .Net
- •Отправка запросов
- •Класс WebClient
- •Классы WebRequest и WebResponse
- •Отправка данных в запросе
- •Обработка ошибок при запросах
- •Класс Socket
- •Общий принцип работы сокетов
- •Клиент-серверное приложение на сокетах tcp
- •Протокол tcp
- •Многопоточное клиент-серверное приложение tcp
- •Консольный tcp-чат
- •NetworkStream и текстовые потоки
- •Потоки бинарных данных
- •Протокол http
- •Руководство по Universal Windows Platform
- •Руководство по ado.Net и работе с базами данных
- •Глава 3. Работа с SqlDataAdapter и DataSet
- •Глава 4. Linq to sql
- •Введение в Entity Framework
- •Что такое Entity Framework
- •Способы взаимодействия с бд
- •Первое приложение с Entity Framework. Подход Code First
- •Взаимодействие с данными. Подходы
- •Code First к существующей базе данных
- •Соглашения по наименованию в Code First
- •Сопоставление типов
- •Названия таблиц и столбцов
- •Автоматизация Code First
- •Автоматизация Code First и ef Power Tools
- •Основы Entity Framework
- •Основные операции с данными
- •Добавление
- •Редактирование
- •Удаление
- •Строка подключения
- •Строка подключения в Model First и Database First
- •Навигационные свойства и lazy loading
- •Способы получения связанных данных
- •Связь один-к-одному
- •Связь один ко многим
- •Связь один ко многим. Практический пример
- •Связь многие ко многим
- •Инициализация базы данных
- •Параллелизм в Entity Framework
- •Управление транзакциями
- •Руководство по программированию для Xamarin Forms
- •Руководство по asp.Net Core
- •Паттерны проектирования в c# и .Net
- •Руководство по игростроению на платформе MonoGame
- •Задания для самостоятельного выполнения Рекомендации по выполнению практикума
- •Лабораторная работа. Алгебра логики и логические задачи.
- •Лабораторная работа. Алгоритмы. Алгоритмизация.
- •Цель и порядок работы
- •Контрольные вопросы
- •Задания
- •Лабораторная работа. Основы c# (.Net)
- •Работа с консолью и класс Console
- •Лабораторная работа. Основные операции с#. Выражения. Преобразование типов.
- •Лабораторная работа. Операторы языка c#
- •Лабораторная работа. Методы: основные понятия
- •Лабораторная работа. Рекурсивные методы
- •I. Разработать рекурсивный метод (возвращающий значение):
- •II. Разработка рекурсивных методов ( не возвращающих значений):
- •Лабораторная работа. Обработка исключений
- •Лабораторная работа. Массивы
- •I. Дана последовательность целых чисел.
- •II. Дана последовательность из n действительных чисел.
- •III. Дан массив размером n×n, элементы которого целые числа.
- •IV. Дан массив размером n×n, элементы которого целые числа.
- •Лабораторная работа. Символы и строки
- •Лабораторная работа. Регулярные выражения
- •Лабораторная работа. Организация с#-системы ввода-вывода
- •I. Работа с двоичными файлами:
- •II. Работа с текстовым (символьным) файлом.
- •Лабораторная работа. Работа с файловой системой
- •Лабораторная работа. Классы: основные понятия, данные, методы, конструкторы, свойства
- •Лабораторная работа. Классы: деструкторы, индексаторы, операции класса, операции преобразования типов
- •Лабораторная работа. Иерархия классов
- •Лабораторная работа. Интерфейсы и структуры
- •Лабораторная работа. Коллекции пространства имен System.Collection
- •Решить следующие задачи с использованием класса Stack:
- •Решить следующие задачи с использованием класса Queue:
- •Решить задачи из предыдущей лабораторной работы, используя класс ArrayList.
- •Лабораторная работа. Делегаты
- •Лабораторная работа. Сборки .Net
- •Лабораторная работа. Многопоточность
- •Лабораторная работа. Парелельное программирование и библиотека tpl.
- •Лабораторная работа. Сетевое программирование c#.
- •Лабораторная работа. Windows Universal Platform.
- •Лабораторная работа. Wup - проект.
- •Лабораторная работа. Ado.Net работа с базами данных
- •1. Библиотека
- •2. Университет
- •3. Оптовая база
- •4. Производство
- •5. Сеть магазинов
- •6. Авторемонтные мастерские
- •7. Деканат
- •8. Договорная деятельность организации
- •9. Поликлиника
- •10. Телефонная станция
- •11. Спорт
- •12. Сельскохозяйственные работы
- •13. Городской транспорт
- •14. География
- •15. Домоуправление
- •16. Аэропорт
- •Лабораторная работа. Entity Framework
- •1. Библиотека
- •2. Университет
- •3. Оптовая база
- •4. Производство
- •5. Сеть магазинов
- •6. Авторемонтные мастерские
- •7. Деканат
- •8. Договорная деятельность организации
- •9. Поликлиника
- •10. Телефонная станция
- •11. Спорт
- •12. Сельскохозяйственные работы
- •13. Городской транспорт
- •14. География
- •15. Домоуправление
- •16. Аэропорт
- •Лабораторная работа. Xamarin Forms
- •Лабораторная работа. Asp.Net mvc 5 / Core
Прерывание параллельной операции
Вполне вероятно, что нам может потребоваться прекратить операцию до ее завершения. В этом случае мы можем использовать метод WithCancellation(), которому в качестве параметра передается токен CancellationToken:
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
new Task(() =>
{
Thread.Sleep(400);
cts.Cancel();
}).Start();
try
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, };
var factorials = from n in numbers.AsParallel().WithCancellation(cts.Token)
select Factorial(n);
foreach (var n in factorials)
Console.WriteLine(n);
}
catch(OperationCanceledException ex)
{
Console.WriteLine("Операция была прервана");
}
catch (AggregateException ex)
{
if (ex.InnerExceptions != null)
{
foreach (Exception e in ex.InnerExceptions)
Console.WriteLine(e.Message);
}
}
finally
{
cts.Dispose();
}
Console.ReadLine();
}
static int Factorial(int x)
{
int result = 1;
for (int i = 1; i <= x; i++)
{
result *= i;
}
Console.WriteLine("Факториал числа {0} равен {1}", x, result);
Thread.Sleep(1000);
return result;
}
В параллельной запущенной задаче вызывается метод cts.Cancel(), что приводит к завершению операции и генерации исключения OperationCanceledException:
При этом также имеет смысл обрабатывать исключение AggregateException, так как если параллельно возникает еще одно исключение, то это исключение, а также OperationCanceledException помещаются внутрь одного объекта AggregateException.
Службы Windows
Создание службы для Windows
Одним из важнейших компонентов ОС Windows являются службы. Фактически это отдельные приложения, которые не имеют графического интерфейса и которые выполняют различные задачи в фоновом режиме. Службы могут быть запущены при старте операционной системы, так и в любой другой момент работы пользователя. Распространенным примером служб являются различные веб-серверы, которые в фоновом режиме прослушивают определенный порт на наличие подключений, и если подключения имеются, то взаимодействуют с ними. Это могут быть также различные вспомогательные сервисы обновлений для других установленных программ, которые обращаются к серверу, чтобы узнать, есть ли новая версия приложения. В общем то мы можем открыть панель служб и сами увидеть все установленные и запущенные службы:
Рассмотрим, как создавать свои службы в C#. В качестве реализуемой задачи выберем наблюдение за изменениями в определенной папке в файловой системе. Теперь создадим для ее выполнения службу.
Вначале создадим новый проект, который будет иметь тип Windows Service. Назовем проект FileWatcherService:
После этого Visual Studio генерирует проект, который имеет все необходимое. Хотя в принципе нам необязательно выбирать именно этот тип проекта, можно было бы создать проект библиотеки классов, и затем в нем определить все необходимые классы.
Итак, новый проект выглядит следующим образом:
Здесь также есть файл Program.cs и есть собственно узел службы Service1.cs.
Служба представляет обычное приложение, но она не запускаетс сама по себе. Все вызовы и обращения к ней проходят через менеджер управления службами (Service Control Manager или SCM). Когда служба запускается автоматически при старте системы или вручную, то SCM обращается к методу Main в классе Program:
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
Метод Main по умолчанию определен таким образом, чтобы запускать сразу несколько служб, которые определены в массиве ServicesToRun. Однако по умолчанию проект содержит только одну службу Service1. Сам запуск производится с помощью метода Run: ServiceBase.Run(ServicesToRun).
Сама запускаемая служба представлена узлом Service1.cs. Однако на самом деле это не простой файл кода. Если мы откроем этот узел, то увидим в нем файл дизайнера службы Service1.Designer.cs и класс Service1.
Класс Service1 собственно представляет службу. По умолчанию он имеет следующий код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace FileWatcherService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
}
Класс службы должен наследоваться от базового класса ServiceBase. Этот класс определяет ряд методов, важнейшие из которых метод OnStart(), который запускает действия, выпоняемые службой, и метод OnStop(), останавливающий службу.
После того, как SCM вызовет метод Main и зарегистрирует слубу, происходит непосредственный ее вызов через запуск метода OnStart.
Когда в консоли служб или через командную строку мы посылаем команду на остановку службы, то SCM обращается к методу OnStop для ее остановки.
Кроме этих двух методов в классе службы можно переопределить еще несколько методов базового класса ServiceBase:
OnPause: вызывается при приостановке службы
OnContinue: вызывается при возобновлении работы службы после ее приостановки
OnShutdown: вызывается при завершении работы Windows
OnPowerEvent: вызывается при изменении режима электропитания
OnCustomCommand: вызывается при получении службой пользовательской команды от Менеджера Управления Службами (Service Control Manager / SCM)
В конструкторе класса Service1 вызывается метод InitializeComponent(), который определен в файле дизайнера Service1.Designer.cs:
namespace FileWatcherService
{
partial class Service1
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Service1";
}
}
}
Единственное, что надо в нем отметить, это установка названия службы (свойство ServiceName):
this.ServiceName = "Service1";
Это то название, которое будет отображаться в консоли служб после установки данной службы. Мы можем его изменить, а можем и оставить как есть.
Теперь изменим код службы следующим образом:
using System;
using System.ServiceProcess;
using System.IO;
using System.Threading;
namespace FileWatcherService
{
public partial class Service1 : ServiceBase
{
Logger logger;
public Service1()
{
InitializeComponent();
this.CanStop = true;
this.CanPauseAndContinue = true;
this.AutoLog = true;
}
protected override void OnStart(string[] args)
{
logger = new Logger();
Thread loggerThread = new Thread(new ThreadStart(logger.Start));
loggerThread.Start();
}
protected override void OnStop()
{
logger.Stop();
Thread.Sleep(1000);
}
}
class Logger
{
FileSystemWatcher watcher;
object obj = new object();
bool enabled = true;
public Logger()
{
watcher = new FileSystemWatcher("D:\\Temp");
watcher.Deleted += Watcher_Deleted;
watcher.Created += Watcher_Created;
watcher.Changed += Watcher_Changed;
watcher.Renamed += Watcher_Renamed;
}
public void Start()
{
watcher.EnableRaisingEvents = true;
while(enabled)
{
Thread.Sleep(1000);
}
}
public void Stop()
{
watcher.EnableRaisingEvents = false;
enabled = false;
}
// переименование файлов
private void Watcher_Renamed(object sender, RenamedEventArgs e)
{
string fileEvent = "переименован в " + e.FullPath;
string filePath = e.OldFullPath;
RecordEntry(fileEvent, filePath);
}
// изменение файлов
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
string fileEvent = "изменен";
string filePath = e.FullPath;
RecordEntry(fileEvent, filePath);
}
// создание файлов
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
string fileEvent = "создан";
string filePath = e.FullPath;
RecordEntry(fileEvent, filePath);
}
// удаление файлов
private void Watcher_Deleted(object sender, FileSystemEventArgs e)
{
string fileEvent = "удален";
string filePath = e.FullPath;
RecordEntry(fileEvent, filePath);
}
private void RecordEntry(string fileEvent, string filePath)
{
lock (obj)
{
using (StreamWriter writer = new StreamWriter("D:\\templog.txt", true))
{
writer.WriteLine(String.Format("{0} файл {1} был {2}",
DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss"), filePath, fileEvent));
writer.Flush();
}
}
}
}
}
Ключевым классом, который инкапсулирует всю функциональность, является класс Logger. С помощью объекта FileSystemWatcher он будет вести мониторинг изменений в папке D://Temp. В методе Start() устанавливается, что мы будем отслеживать изменения через объект FileSystemWatcher. И вся работа будет идти, пока булевая переменная enabled равнаtrue. А метод Stop() позволит завершить работу класса.
События FileSystemWatcher позволяют отслеживать все изменения в наблюдаемой папке. При этом будет вестись запись изменений в файл templog.txt. Чтобы не было гонки ресурсов за файл templog.txt, в который вносятся записи об изменениях, процедура записи блокируется заглушкой lock(obj).
В итоге после создания, изменения, переименования и удаления файл лога будет содержать что-то наподобие:
30.07.2015 12:15:40 файл D:\Temp\Новый текстовый документ.txt был создан
30.07.2015 12:15:46 файл D:\Temp\Новый текстовый документ.txt был переименован в D:\Temp\hello.txt
30.07.2015 12:15:55 файл D:\Temp\hello.txt был изменен
30.07.2015 12:15:55 файл D:\Temp\hello.txt был изменен
30.07.2015 12:16:01 файл D:\Temp\hello.txt был удален
В самом классе службы Service1 в конструкторе устанавливается ряд опций:
this.CanStop = true; // службу можно остановить
this.CanPauseAndContinue = true; // службу можно приостановить и затем продолжить
this.AutoLog = true; // служба может вести запись в лог
В методе OnStart() для запуска объекта Logger вызывется новый поток:
protected override void OnStart(string[] args)
{
logger = new Logger();
Thread loggerThread = new Thread(new ThreadStart(logger.Start));
loggerThread.Start();
}
Новый поток нужен, так как текущий поток обрабатывает только команды SCM и должен возвращаться из метода OnStart как можно быстрее.
Когда от менеджера SCM поступает команда на остановку службы, срабатывает метод OnStop, который вызывает методlogger.Stop(). Дополнительная задержка позволит потоку логгера остановиться:
protected override void OnStop()
{
logger.Stop();
Thread.Sleep(1000);
}
Однако самого класса службы еще недостаточно. Нам необходимо еще создать устанощик службы.
