TaskCompletionSource<T>
TaskCompletionSource<T> (TCS) — это мощный инструмент в .NET, который позволяет вам создавать и управлять задачами (Task<T>) вручную. Он предоставляет методы для завершения задачи с результатом, исключением или отменой.
Давайте рассмотрим простой пример, чтобы понять, как работает TaskCompletionSource<T>.
Пример: Создание задачи с использованием TaskCompletionSource<T>
Предположим, у нас есть метод, который асинхронно вычисляет квадрат числа. Мы хотим использовать TaskCompletionSource<int> для управления завершением этой задачи.
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main(string[] args)
{
var tcs = new TaskCompletionSource<int>();
// Запускаем асинхронную операцию
CalculateSquare(5, tcs);
// Ожидаем завершения задачи
int result = await tcs.Task;
Console.WriteLine($"Result: {result}");
}
public static void CalculateSquare(int number, TaskCompletionSource<int> tcs)
{
// Имитация асинхронной операции
Task.Run(() =>
{
int square = number * number;
tcs.SetResult(square); // Завершаем задачу с результатом
});
}
}
Объяснение
Создание TaskCompletionSource<int>:
var tcs = new TaskCompletionSource<int>();
Мы создаем экземпляр TaskCompletionSource<int>, который будет управлять задачей.
Запуск асинхронной операции:
CalculateSquare(5, tcs);
Мы вызываем метод CalculateSquare, который принимает число и TaskCompletionSource<int>.
Асинхронная операция:
public static void CalculateSquare(int number, TaskCompletionSource<int> tcs)
{
Task.Run(() =>
{
int square = number * number;
tcs.SetResult(square); // Завершаем задачу с результатом
});
}
Внутри метода CalculateSquare мы запускаем асинхронную операцию с помощью Task.Run. После вычисления квадрата числа мы вызываем tcs.SetResult(square), чтобы завершить задачу с результатом.
Ожидание завершения задачи:
int result = await tcs.Task;
В методе Main мы ожидаем завершения задачи с помощью await tcs.Task. Когда задача завершится, мы получим результат и выведем его на консоль.
Основные методы TaskCompletionSource<T>
- SetResult(T result): Завершает задачу с указанным результатом.
- SetException(Exception exception): Завершает задачу с указанным исключением.
- SetCanceled(): Завершает задачу как отмененную.
- TrySetResult(T result): Попытка завершить задачу с указанным результатом. Возвращает true, если задача была успешно завершена, и false, если задача уже была завершена.
- TrySetException(Exception exception): Попытка завершить задачу с указанным исключением.
- TrySetCanceled(): Попытка завершить задачу как отмененную.
Пример с таймаутом
Теперь давайте рассмотрим пример с таймаутом, чтобы понять, как можно использовать TaskCompletionSource<T> для управления завершением задачи с учетом времени ожидания.
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main(string[] args)
{
var tcs = new TaskCompletionSource<int>();
// Запускаем асинхронную операцию
CalculateSquareWithDelay(5, tcs);
// Запускаем таймаут
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(1)).ContinueWith(_ => tcs.TrySetCanceled());
// Ожидаем завершения одной из задач
var completedTask = await Task.WhenAny(tcs.Task, timeoutTask);
if (completedTask == timeoutTask)
{
Console.WriteLine("Operation timed out.");
}
else
{
int result = await tcs.Task;
Console.WriteLine($"Result: {result}");
}
}
public static void CalculateSquareWithDelay(int number, TaskCompletionSource<int> tcs)
{
Task.Run(async () =>
{
await Task.Delay(500); // Имитация задержки
int square = number * number;
tcs.SetResult(square); // Завершаем задачу с результатом
});
}
}
Объяснение
Создание TaskCompletionSource<int>:
var tcs = new TaskCompletionSource<int>();
Запуск асинхронной операции:
CalculateSquareWithDelay(5, tcs);
Запуск таймаута:
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(1)).ContinueWith(_ => tcs.TrySetCanceled());
Мы создаем задачу таймаута, которая завершит TaskCompletionSource<int> как отмененную, если операция не завершится в течение 1 секунды.
Ожидание завершения одной из задач:
var completedTask = await Task.WhenAny(tcs.Task, timeoutTask);
Мы ожидаем завершения одной из задач (асинхронной операции или таймаута) с помощью Task.WhenAny
.
Проверка завершенной задачи:
if (completedTask == timeoutTask)
{
Console.WriteLine("Operation timed out.");
}
else
{
int result = await tcs.Task;
Console.WriteLine($"Result: {result}");
}
Если завершилась задача таймаута, выводим сообщение о таймауте. В противном случае получаем результат и выводим его на консоль.
Этот пример демонстрирует, как можно использовать TaskCompletionSource<T> для управления завершением задачи с учетом времени ожидания.
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.