Конспект лекции "Многопоточность" :()=[,`][]=
// Задачи и класс Task
Первый способ создание объекта Task и вызов у него метода Start:
Task task = new Task(
() => Console.WriteLine("Hello Task!")
);
task.Start();
Process finished with exit code 0.
Второй способ заключается в использовании статического метода Task.Factory.StartNew()
Task task = Task.Factory.StartNew(
() => Console.WriteLine("Hello Task!")
);
Process finished with exit code 0.
Третий способ определения и запуска задач представляет использование статического метода Task.Run():
Task task = Task.Run(
() => Console.WriteLine("Hello Task!")
);
Process finished with exit code 0.
Определим небольшую программу, где используем все эти способы:
using System;
using System.Threading.Tasks;
Task task1 = new Task(
() => Console.WriteLine("Task1 is executed"));
task1.Start();
Task task2 = Task.Factory.StartNew(
() => Console.WriteLine("Task2 is executed"));
Task task3 = Task.Run(
() => Console.WriteLine("Task3 is executed"));
Console.ReadLine();
Task2 is executed
Task1 is executed
Task3 is executed
Process finished with exit code 0.
// Ожидание задачи
esempio
using System;
using System.Threading;
Task task = new Task(Display);
task.Start();
Console.WriteLine(
"Завершение метода Main");
Console.ReadLine();
static void Display()
{
Console.WriteLine(
"Начало работы метода Display");
Console.WriteLine(
"Завершение работы метода Display");
}
Завершение метода Main
Начало работы метода Display
Завершение работы метода Display
Process finished with exit code 0.
// Aсинхронное программирование. Асинхронные методы, async и await
пример асинхронного метода:
using System;
using System.Threading;
using System.Threading.Tasks;
// вызов асинхронного метода
FactorialAsync();
Console.WriteLine(
"Введите число: ");
int n = Int32.Parse(Console.ReadLine());
Console.WriteLine(
$"Квадрат числа равен {n * n}");
Console.Read();
static void Factorial()
{
int result = 1;
for(int i = 1; i <= 6; i++)
{
result *= i;
}
Thread.Sleep(8000);
Console.WriteLine(
$"Факториал равен {result}");
}
// определение асинхронного метода
static async void FactorialAsync()
{
// выполняется синхронно
Console.WriteLine(
"Начало метода FactorialAsync");
// выполняется асинхронно
await Task.Run(()=>Factorial());
Console.WriteLine(
"Конец метода FactorialAsync");
}
Начало метода FactorialAsync
Введите число:
7
Квадрат числа равен 49
Факториал равен 720
Конец метода FactorialAsync
Process finished with exit code 0.
esempio - чтение-запись файла:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
ReadWriteAsync();
Console.WriteLine("Некоторая работа");
Console.Read();
static async void ReadWriteAsync()
{
string s = "Hello world! One step at a time";
// hello.txt - файл, который будет записываться и считываться
using (StreamWriter writer = new StreamWriter("hello.txt", false))
{
// асинхронная запись в файл
await writer.WriteLineAsync(s);
}
using (StreamReader reader = new StreamReader("hello.txt"))
{
// асинхронное чтение из файла
string result = await reader.ReadToEndAsync();
Console.WriteLine(result);
}
}
Некоторая работа
Hello world! One step at a time
Process finished with exit code 0.
мы сами можем определить асинхронную операцию, используя метод Task.Run():
static void Factorial()
{
int result = 1;
for (int i = 1; i <= 6; i++)
{
result *= i;
}
Thread.Sleep(8000);
Console.WriteLine($"Факториал равен {result}");
}
// определение асинхронного метода
static async void FactorialAsync()
{
// вызов асинхронной операции
await Task.Run(()=>Factorial());
}
Process finished with exit code 0.
Можно определить асинхронную операцию с помощью лямбда-выражения:
static async void FactorialAsync()
{
await Task.Run(() =>
{
int result = 1;
for (int i = 1; i <= 6; i++)
{
result *= i;
}
Thread.Sleep(8000);
Console.WriteLine($"Факториал равен {result}");
});
}
Process finished with exit code 0.
// Передача параметров в асинхронную операцию
мы хотим вычислить факториалы разных чисел:
using System;
using System.Threading;
using System.Threading.Tasks;
FactorialAsync(5);
FactorialAsync(6);
Console.WriteLine("Некоторая работа");
Console.Read();
static void Factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
Thread.Sleep(5000);
Console.WriteLine($"Факториал равен {result}");
}
// определение асинхронного метода
static async void FactorialAsync(int n)
{
await Task.Run(()=>Factorial(n));
}
Некоторая работа
Факториал равен 120
Факториал равен 720
Process finished with exit code 0.
// Получение результата из асинхронной операции
using System;
using System.Threading;
using System.Threading.Tasks;
FactorialAsync(5);
FactorialAsync(6);
Console.Read();
static int Factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
return result;
}
// определение асинхронного метода
static async void FactorialAsync(int n)
{
int x = await Task.Run(()=>Factorial(n));
Console.WriteLine($"Факториал равен {x}");
}
Факториал равен 120
Факториал равен 720
Process finished with exit code 0.
// Возвращение результата из асинхронного метода
void
static void Factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
Console.WriteLine($"Факториал равен {result}");
}
// определение асинхронного метода
static async void FactorialAsync(int n)
{
await Task.Run(()=>Factorial(n));
}
Process finished with exit code 0.
Task
using System;
using System.Threading.Tasks;
FactorialAsync(5);
FactorialAsync(6);
Console.WriteLine("Некоторая работа");
Console.Read();
static void Factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
Console.WriteLine($"Факториал равен {result}");
}
// определение асинхронного метода
static async Task FactorialAsync(int n)
{
await Task.Run(()=>Factorial(n));
}
Факториал равен 120
Факториал равен 720
Некоторая работа
Process finished with exit code 0.
Task
using System;
using System.Threading.Tasks;
int n1 = await FactorialAsync(5);
int n2 = await FactorialAsync(6);
Console.WriteLine($"n1={n1} n2={n2}");
Console.Read();
static int Factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
return result;
}
// определение асинхронного метода
static async Task<int> FactorialAsync(int n)
{
return await Task.Run(()=>Factorial(n));
}
n1=120 n2=720
Process finished with exit code 0.
// Последовательный и параллельный вызов асинхронных операций
using System;
using System.Threading.Tasks;
FactorialAsync();
Console.Read();
static void Factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
Console.WriteLine($"Факториал числа {n} равен {result}");
}
// определение асинхронного метода
static async void FactorialAsync()
{
await Task.Run(() => Factorial(4));
await Task.Run(() => Factorial(3));
await Task.Run(() => Factorial(5));
}
Факториал числа 4 равен 24
Факториал числа 3 равен 6
Факториал числа 5 равен 120
Process finished with exit code 0.
// Обработка ошибок в асинхронных методах
Обработка ошибок в асинхронных методах, использующих ключевые слова async и await, имеет свои особенности.
using System;
using System.Threading;
using System.Threading.Tasks;
FactorialAsync(-4);
FactorialAsync(6);
Console.Read();
static void Factorial(int n)
{
if (n < 1)
throw new Exception($"{n} : число не должно быть меньше 1");
int result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
Console.WriteLine($"Факториал числа {n} равен {result}");
}
static async void FactorialAsync(int n)
{
try
{
await Task.Run(() => Factorial(n));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Факториал числа 6 равен 720
-4 : число не должно быть меньше 1
Process finished with exit code 0.
поломанный код
static async void FactorialAsync(int n)
{
Task task = null;
try
{
task = Task.Run(()=>Factorial(n));
await task;
}
catch (Exception ex)
{
Console.WriteLine(task.Exception.InnerException.Message);
Console.WriteLine($"IsFaulted: {task.IsFaulted}");
}
}
error
эксепшен не эксепшен, вывод с неба упал
static async Task DoMultipleAsync()
{
Task allTasks = null;
try
{
Task t1 = Task.Run(()=>Factorial(-3));
Task t2 = Task.Run(() => Factorial(-5));
Task t3 = Task.Run(() => Factorial(-10));
allTasks = Task.WhenAll(t1, t2, t3);
await allTasks;
}
catch (Exception ex)
{
Console.WriteLine("Исключение: " + ex.Message);
Console.WriteLine("IsFaulted: " + allTasks.IsFaulted);
foreach (var inx in allTasks.Exception.InnerExceptions)
{
Console.WriteLine("Внутреннее исключение: " + inx.Message);
}
}
}
Исключение: -3 : число не должно быть меньше 1
IsFaulted: True
Внутреннее исключение: -3: число не должно быть меньше 1
Внутреннее исключение: -5: число не должно быть меньше 1
Внутреннее исключение: -10: число не должно быть меньше 1
никакой возможности нет, это афера
static async void FactorialAsync(int n)
{
try
{
await Task.Run(() => Factorial(n)); ;
}
catch (Exception ex)
{
await Task.Run(()=>Console.WriteLine(ex.Message));
}
finally
{
await Task.Run(() => Console.WriteLine("await в блоке finally"));
}
}
error
// Отмена асинхронных операций
using System;
using System.Threading;
using System.Threading.Tasks;
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
FactorialAsync(6, token);
Thread.Sleep(3000);
cts.Cancel();
Console.Read();
static void Factorial(int n, CancellationToken token)
{
int result = 1;
for (int i = 1; i <= n; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine(
"Операция прервана токеном");
return;
}
result *= i;
Console.WriteLine(
$"Факториал числа {i} равен {result}");
Thread.Sleep(1000);
}
}
// определение асинхронного метода
static async void FactorialAsync(int n, CancellationToken token)
{
if(token.IsCancellationRequested)
return;
await Task.Run(()=>Factorial(n, token));
}
Факториал числа 1 равен 1
Факториал числа 2 равен 2
Факториал числа 3 равен 6
Операция прервана токеном
Process finished with exit code 0.