← Назад к вопросам

Что такое TaskFactory?

2.0 Middle🔥 11 комментариев
#ASP.NET и Web API

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# TaskFactory в C#

TaskFactory - это класс в System.Threading.Tasks, который предоставляет методы для создания и управления Task'ами. Это фабрика для создания асинхронных операций с дополнительными опциями конфигурации.

Основная идея

Вместо того чтобы напрямую использовать Task.Run(), можно использовать TaskFactory для большей гибкости:

// Task.Run - простой способ
var task1 = Task.Run(() => DoWork());

// TaskFactory - более гибкий способ
var taskFactory = new TaskFactory();
var task2 = taskFactory.StartNew(() => DoWork());

Основные методы TaskFactory

1. StartNew - Создание и запуск Task

var factory = new TaskFactory();

// Простой запуск
var task = factory.StartNew(() => 
{
    Console.WriteLine("Work started");
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine("Work completed");
});

await task;

// С результатом
var taskWithResult = factory.StartNew(() => 
{
    return CalculatePi();
});

var result = await taskWithResult;  // double
Console.WriteLine($"Pi = {result}");

2. ContinueWhenAll - Выполнение после всех Task'ов

var factory = new TaskFactory();

// Создаём несколько задач
var task1 = factory.StartNew(() => 
{
    System.Threading.Thread.Sleep(1000);
    return "Task 1 done";
});

var task2 = factory.StartNew(() => 
{
    System.Threading.Thread.Sleep(2000);
    return "Task 2 done";
});

var task3 = factory.StartNew(() => 
{
    System.Threading.Thread.Sleep(500);
    return "Task 3 done";
});

// Продолжение после ВСЕХ задач
var continuation = factory.ContinueWhenAll(
    new[] { task1, task2, task3 },
    tasks => 
    {
        Console.WriteLine("All tasks completed!");
        foreach (var t in tasks)
        {
            var result = ((Task<string>)t).Result;
            Console.WriteLine(result);
        }
    }
);

await continuation;

3. ContinueWhenAny - Выполнение после любого Task'а

var factory = new TaskFactory();

var task1 = factory.StartNew(() => 
{
    System.Threading.Thread.Sleep(3000);
    return "First";
});

var task2 = factory.StartNew(() => 
{
    System.Threading.Thread.Sleep(1000);
    return "Second";
});

// Продолжение после ПЕРВОГО завершённого
var continuation = factory.ContinueWhenAny(
    new Task[] { task1, task2 },
    task => 
    {
        var result = ((Task<string>)task).Result;
        Console.WriteLine($"First completed: {result}");
    }
);

await continuation;

TaskFactory с опциями

// С опциями планирования
var factory = new TaskFactory(
    CancellationToken.None,                    // Токен отмены
    TaskCreationOptions.LongRunning,           // Опции создания
    TaskScheduler.Default                      // Планировщик
);

var task = factory.StartNew(() => 
{
    // Длительная операция
    for (int i = 0; i < 10; i++)
    {
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine($"Iteration {i}");
    }
});

TaskCreationOptions

var factory = new TaskFactory();

// LongRunning - создаёт отдельный поток для долгих операций
var longTask = factory.StartNew(
    () => { /* долгая операция */ },
    TaskCreationOptions.LongRunning
);

// AttachedToParent - связывает с родительским Task'ом
var parentTask = Task.Run(() => 
{
    var childTask = factory.StartNew(
        () => Console.WriteLine("Child"),
        TaskCreationOptions.AttachedToParent
    );
});

await parentTask;  // Ждёт и детей

// DenyChildAttach - запрещает детским Task'ам привязываться
var restrictedFactory = new TaskFactory(
    CancellationToken.None,
    TaskCreationOptions.DenyChildAttach,
    TaskScheduler.Default
);

TaskFactory vs Task.Run

// Task.Run - более простой и современный способ
var task1 = Task.Run(() => DoWork());
var task2 = Task.Run(async () => await DoWorkAsync());

// TaskFactory - более гибкий контроль
var factory = new TaskFactory(
    CancellationToken.None,
    TaskCreationOptions.LongRunning,
    TaskScheduler.Current
);
var task3 = factory.StartNew(() => DoWork());

// Практически эквивалентно
var task4 = Task.Factory.StartNew(() => DoWork());

Практические примеры

Пример 1: Параллельная обработка данных

public async Task ProcessDataInParallel()
{
    var factory = new TaskFactory();
    
    var data = Enumerable.Range(1, 100).ToList();
    var tasks = data
        .Select(item => factory.StartNew(() => 
        {
            Console.WriteLine($"Processing {item} on thread {Thread.CurrentThread.ManagedThreadId}");
            return item * 2;
        }))
        .ToList();
    
    var results = await Task.WhenAll(tasks);
    Console.WriteLine($"Processed {results.Length} items");
}

Пример 2: Цепочка операций

public async Task ChainedOperations()
{
    var factory = new TaskFactory();
    
    // Первая операция
    var task1 = factory.StartNew(() => 
    {
        System.Threading.Thread.Sleep(1000);
        return "Step 1 complete";
    });
    
    // Вторая операция после первой
    var task2 = factory.ContinueWith(task1, t => 
    {
        var previous = t.Result;
        System.Threading.Thread.Sleep(500);
        return $"{previous}, Step 2 complete";
    });
    
    // Третья операция после второй
    var task3 = factory.ContinueWith(task2, t => 
    {
        var previous = t.Result;
        System.Threading.Thread.Sleep(500);
        return $"{previous}, Step 3 complete";
    });
    
    var result = await task3;
    Console.WriteLine(result);
}

Пример 3: Отмена операций

public async Task CancellableOperation()
{
    var cts = new CancellationTokenSource();
    var factory = new TaskFactory(cts.Token);
    
    var task = factory.StartNew(() => 
    {
        for (int i = 0; i < 100; i++)
        {
            cts.Token.ThrowIfCancellationRequested();
            
            System.Threading.Thread.Sleep(100);
            Console.WriteLine($"Progress: {i}%");
        }
    });
    
    // Отмена через 2 секунды
    _ = Task.Delay(2000).ContinueWith(_ => cts.Cancel());
    
    try
    {
        await task;
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("Operation cancelled");
    }
}

Пример 4: Обработка ошибок

public async Task ErrorHandling()
{
    var factory = new TaskFactory();
    
    var task = factory.StartNew(() => 
    {
        throw new InvalidOperationException("Something went wrong");
    });
    
    try
    {
        await task;
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
}

Task.Factory shortcut

Вместо создания нового TaskFactory, можно использовать статический Task.Factory:

// Это одно и то же
var factory1 = new TaskFactory();
var factory2 = Task.Factory;

// Task.Factory - это синглтон по умолчанию
var task = Task.Factory.StartNew(() => DoWork());
var continued = Task.Factory.ContinueWhenAll(/* ... */);

Когда использовать TaskFactory

Используй TaskFactory, если:

  • Нужен контроль над TaskCreationOptions
  • Нужны ContinueWhen* методы
  • Нужно использовать кастомный TaskScheduler
  • Нужна гибкость в управлении Task'ами

Используй Task.Run, если:

  • Простой случай - просто запустить асинхронный код
  • Работаешь с async/await
  • Не нужны продвинутые опции
// Пример: Когда выбрать что-то

// Task.Run - простой случай
var result = await Task.Run(() => CalculateSomething());

// TaskFactory - сложный случай с зависимостями
var factory = new TaskFactory();
var task1 = factory.StartNew(() => FetchData());
var task2 = factory.StartNew(() => ProcessData());
var combined = factory.ContinueWhenAll(
    new[] { task1, task2 },
    tasks => CombineResults(tasks)
);

Заключение

TaskFactory - это мощный инструмент для создания и управления асинхронными операциями в .NET. Основные возможности:

  • StartNew - создание и запуск Task
  • ContinueWith - выполнение после другого Task
  • ContinueWhenAll - выполнение после всех Task'ов
  • ContinueWhenAny - выполнение после первого Task
  • Опции - контроль над планированием и поведением

Хотя в современном коде рекомендуется использовать async/await и Task.Run, TaskFactory остаётся полезным инструментом для сложных сценариев координации асинхронных операций.

Что такое TaskFactory? | PrepBro