Подтвердить что ты не робот

Как связать асинхронные операции с библиотекой параллельных задач в .NET 4?

Я пытаюсь программно организовать асинхронные операции в С# 4, такие как Writes для данного объекта Stream. Я изначально сделал это "вручную", подключив обратные вызовы от одной операции к следующей, но я подумал, что попробую параллельную библиотеку задач .NET 4, чтобы избавить себя от необходимости повторно изобретать параллельное колесо.

Для начала я переношу свои асинхронные вызовы в Задачи, например:

public static Task CreateWriteTask(Stream stream, byte[] data)
{
    return Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, data, 0, data.Length, null);
}

Продолжения упрощали синхронные операции цепочки (если вы извините неудачное имя метода):

public static Task ChainFlush(Stream stream, Task precedingTask)
{
    return precedingTask.ContinueWith(x => stream.Flush());
}

Но нет версии метода Task.ContinueWith, который принимает операцию async так же, как TaskFactory.FromAsync.

Итак, предполагая, что я продолжаю использовать TPL, я ищу правильную реализацию этого метода:

public static Task ChainWrite(Stream stream, byte[] data, Task precedingTask)
{
    //?
}
4b9b3361

Ответ 1

Моя лучшая идея заключается в том, чтобы связать создание новой задачи записи, а затем использовать метод расширения Unwrap, чтобы превратить Task<Task> обратно в Task:

public static Task ChainWrite(Stream stream, byte[] data, Task precedingTask)
{
    return precedingTask.ContinueWith(x => CreateWriteTask(stream, data)).Unwrap();
}

Ответ 2

Насколько я понимаю, это неудачное последствие неконтролируемого запуска задачи. Поскольку вы никогда не знаете, когда запускается задача, перегрузка не может быть такой, как

precedingTask.ContinueWith(Task nextTask)

поскольку после его создания он может быть запущен, когда вы перейдете в "ContinueWith". Кроме того, это также создавало бы беспорядок типов. Какой должен быть тип здесь:

precedingTask<T>.ContinueWith(Task<..what?..> nextTask)

before возвращает значение T, поэтому следующее берет то, что и что возвращает? Однако это можно решить с помощью закрытий.

Ответ 3

Попробуйте ContinueWhenAll() или ContinueWhenAny() вместо ContinueWith(). См. здесь.