Как связать асинхронные операции с библиотекой параллельных задач в .NET 4? - PullRequest
17 голосов
/ 07 сентября 2010

Я пытаюсь программно связать асинхронные операции в C # 4, такие как запись в заданный объект 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, которая принимает асинхронную операцию так же, как TaskFactory.FromAsync.

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

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

Ответы [ 3 ]

12 голосов
/ 07 сентября 2010

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

public static Task ChainWrite(Stream stream, byte[] data, Task precedingTask)
{
    return precedingTask.ContinueWith(x => CreateWriteTask(stream, data)).Unwrap();
}
3 голосов
/ 16 октября 2010

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

precedingTask.ContinueWith(Task nextTask)

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

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

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

1 голос
/ 08 сентября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...