Почему автор использует варианты методов ContinueWith () и async, когда это кажется бессмысленным - PullRequest
0 голосов
/ 08 октября 2018

Я недавно читал Essential C # 6.0.В главе книги, где автор объясняет многопоточность, он показывает этот метод, и я не понимаю двух вещей, которые нигде не объясняются.

private static Task WriteWebRequestSizeAsync(string url)
{
    StreamReader reader = null;
    WebRequest webRequest = WebRequest.Create(url);

    Task task = webRequest.GetResponseAsync()
        .ContinueWith(antecedent =>
        {
            WebResponse response = antecedent.Result;
            reader = new StreamReader(response.GetResponseStream());
            return reader.ReadToEndAsync();
        })
        .Unwrap()
        .ContinueWith(antecedent =>
        {
            if(reader != null) reader.Dispose();
            string text = antecedent.Result;
            Console.WriteLine(text.Length);
        });
    return task;
}

1. Почему автор использует ContinueWith() методы и называет их essential ?Как его способ сделать это лучше, чем мой подход, который не использует эти методы?

private static Task WriteWebRequestSizeAsync(string url)
{
    return Task.Run(() =>
    {
        WebRequest webRequest = WebRequest.Create(url);
        WebResponse response = webRequest.GetResponseAsync().Result;
        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
        {
            string text = reader.ReadToEndAsync().Result;
            Console.WriteLine(text.Length);
        }
    });
}

2. Почему автор использует async вариантыметоды и затем получают доступ к их результату через свойство .Result, вместо использования не асинхронных вариантов, так как в конце он, похоже, имеет тот же результат. Пожалуйста, обратите внимание, что я не изменил его в моем подходе выше

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

Основное различие между вами и авторами состоит в том, что автор запускает код в том же потоке, что и метод WriteWebRequestSizeAsync, в то время как ваш код будет выполняться в каком-то потоке из ThreadPull.Я не знаю контекста, поэтому, может быть, это важно.По поводу второго вопроса.Если автор вызывает не асинхронные методы, он не может получить задачи и присоединиться к ним ContinueWith.

0 голосов
/ 08 октября 2018

Несмотря на то, что вы вызываете GetResponseAsync () в вашем методе, попытка использовать .Result делает это блокирующим вызовом. В результате этого ваша задача продолжает ждать, пока результат станет доступным, тратя впустую циклы процессора.

WebResponse response = webRequest.GetResponseAsync().Result; //blocking call

Однако в примере автора за GetResponseAsync () следует ContinueWith ().Это означает, что Задача, для которой вызывается GetResponseAsync (), не будет заблокирована и может быть использована для каких-либо других действий.Когда станет доступен результат GetResponseAsync (), будет запущено продолжение.

 webRequest.GetResponseAsync()
        .ContinueWith(antecedent =>
        {
            WebResponse response = antecedent.Result;
            reader = new StreamReader(response.GetResponseStream());
            return reader.ReadToEndAsync();
        })

Этот же пример можно написать с использованием async и await вместо продолжения ... Это будет иметь аналогичный эффект продолжения.Тем не менее, это будет более естественным для чтения.

var result = await webRequest.GetResponseAsync();
//do something with result now.
0 голосов
/ 08 октября 2018

Создается впечатление, что автор использует сложенное продолжение, чтобы разделить операции в соответствии с принципом разделения интересов.

...