Последовательность выполнения TransformBlock потока данных TPL выглядит не по порядку / асинхронно
Я следую этому пошаговому руководству по MSDN - Пошаговое руководство. Создание конвейера потока данных. Я создал сингл TransformBlock
и выполнил это, выполнив Post
к этому.
// Process "The Adventurous Life of a Versatile Artist: Houdini"
// by Harry Houdini.
downloadString.Post("http://www.gutenberg.org/cache/epub/45370/pg45370.txt");
Затем после этого я называю Complete
метод и есть Console.WriteLine("Press a key to exit:");
линия.
Вот полный код. Вы также можете найти его на этом этапе в этом коммите на моем репозитории github.
using System;
using System.Net.Http;
using System.Threading.Tasks.Dataflow;
namespace Palindromes.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
//
// Create members of the Pipeline
//
// Download the requested resource as a string
var downloadString = new TransformBlock<string, string>
( url =>
{
Console.WriteLine($"Downloading from {url}...");
string result = null;
using (var client = new HttpClient())
{
// Perform a synchronous call by calling .Result
var response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
// read result synchronously by calling .Result
result = responseContent.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(result))
Console.WriteLine($"Downloaded {result.Length} characters...");
}
}
return result;
}
);
// Process "The Adventurous Life of a Versatile Artist: Houdini"
// by Harry Houdini.
downloadString.Post("http://www.gutenberg.org/cache/epub/45370/pg45370.txt");
downloadString.Complete();
Console.WriteLine("Press a key to exit:");
Console.ReadKey();
}
}
}
Когда я запускаю это консольное приложение, я ожидаю увидеть вывод следующим образом.
Ожидаемый результат
Downloading from http://www.gutenberg.org/cache/epub/45370/pg45370.txt...
Downloaded 129393 characters...
Press a key to exit:
Но вот фактический результат. (Я запускал его несколько раз с той же последовательностью Console.WriteLine
выход показывая вверх.
Фактический вывод
Press a key to exit:
Downloading from http://www.gutenberg.org/cache/epub/45370/pg45370.txt...
Downloaded 129393 characters...
Почему Press a key to exit
линия выполняется до TransformBlock
"s Console.WriteLine
Вам позвонили?
Не должен TransformBlock
"s Console.WriteLine
быть вызванным первым, так как я вызываю его первым, и так как это будет частью конвейера? Также у меня нет никаких async
насколько я могу судить, я не знаю полностью внутреннюю работу потока данных TPL, так почему же это происходит не по порядку?
Спасибо!
2 ответа
Почему Нажмите клавишу для выхода из строки, выполняемой перед вызовом TransformBlock Console.WriteLines?
Призыв к Console.WriteLine("Press a key to exit:")
происходит до TransformBlock
завершил функцию преобразования. Каждый элемент размещен на TransfromBlock
будет обрабатываться асинхронно с учетом вашего основного контекста.
Если вы хотите подождать, пока закончится конвейер, вам нужно будет либо заблокировать его Completion Task
или же await
завершение в async
метод:
private static async Task MainAsync() {
// Process "The Adventurous Life of a Versatile Artist: Houdini"
// by Harry Houdini.
downloadString.Post("http://www.gutenberg.org/cache/epub/45370/pg45370.txt");
downloadString.Complete();
await downloadString.Completion;
}
Post
Метод вернется после того, как размещенный элемент будет сохранен во входной очереди блока, он не будет ждать его обработки.
Этот метод вернется, как только целевой блок решит принять или отклонить элемент, но, если иное не определено специальной семантикой целевого блока, он не ожидает фактической обработки элемента. Например, ActionBlock вернется из Post, как только он сохранит опубликованный элемент в своей входной очереди).
Элементы из входной очереди затем обрабатываются асинхронно.