簡體   English   中英

當看起來毫無意義時,為什么作者使用ContinueWith()和異步方法變體

[英]Why does the author use ContinueWith() and async methods variants when it seems pointless

我最近一直在閱讀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()方法並將其稱為必不可少的 與未使用這些方法的方法相比,他的方法做得如何?

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.為什么作者使用方法的異步變體,然后通過.Result屬性訪問其結果,而不是使用非異步變體,因為它看起來在最后具有相同的結果。 請注意,我在上面的方法中沒有更改它

雖然你在你的方法調用GetResponseAsync(),但是,試圖使用.Result使它成為阻擋call.As這樣的結果你的任務繼續等待的結果是可用的浪費CPU周期。

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

但是,在作者的示例中,GetResponseAsync()之后是ContinueWith()。 這意味着在其上調用GetResponseAsync()的Task不會被阻塞,並且可以用於執行其他操作。 當GetResponseAsync()的結果可用時,將繼續運行。

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

也可以使用async和await而不是continuation來編寫相同的示例...這將具有continuation的類似效果。 但是,閱讀起來會更自然。

var result = await webRequest.GetResponseAsync();
//do something with result now.

似乎作者使用了堆疊的連續性,以便根據關注點分離原則拆分操作。

與您的作者方式之間的主要區別在於,作者使用哪種方法在同一線程中運行WriteWebRequestSizeAsync方法中的代碼,而您的代碼將在ThreadPull中的某些線程中運行。 我不知道背景,所以可能是必不可少的。 關於第二個問題。 如果作者調用了非異步方法,那么他將無法獲取任務並將其附加到ContinueWith

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM