簡體   English   中英

為什么有些異步方法需要Task的返回類型,而另一些則不需要

[英]Why do some async methods require a return type of Task, and others don't

在Microsoft的此示例中 ,該方法的返回類型為Task<int>

范例1:

async Task<int> AccessTheWebAsync()
{ 
    // You need to add a reference to System.Net.Http to declare client.
    HttpClient client = new HttpClient();

    // GetStringAsync returns a Task<string>. That means that when you await the 
    // task you'll get a string (urlContents).
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();

    // The await operator suspends AccessTheWebAsync. 
    //  - AccessTheWebAsync can't continue until getStringTask is complete. 
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    //  - Control resumes here when getStringTask is complete.  
    //  - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask;

    // The return statement specifies an integer result. 
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    return urlContents.Length;
}

在第二個示例中,它使用async和await,但是BUT不返回Task <>類型,為什么?

范例2:

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            ReadCharacters();
        }

        static async void ReadCharacters()
        {
            String result;
            using (StreamReader reader = File.OpenText("existingfile.txt"))
            {
                Console.WriteLine("Opened file.");
                result = await reader.ReadToEndAsync();
                Console.WriteLine("Contains: " + result);
            }
        }
    }
}

第三,在第一個示例中,是否可以返回一個數組(字符串)?

在第二個示例中,它使用async和await,但是BUT不返回Task <>類型,為什么?

他們犯了一個錯誤。 每當創建異步且沒有返回值的方法時 ,它都應返回Task 唯一的例外是事件處理程序,您需要在其中與委托簽名保持兼容性,但事實並非如此。 Task視為異步方法的void等效項。

為什么您實際上返回一個Task而不是void 因為返回Task可以監視執行狀態,還可以正確處理封裝在正在進行的操作中的所有異常。

例如,考慮拋出一個async void方法:

public async void WaitAndThrowAsync()
{
    await Task.Delay(1000);
    throw new Exception("yay");
}

public void CallWaitAndThrowAsync()
{
    // What happens when it throws here?
    WaitAndThrowAsync();
}

調用此方法時,您無法實際處理方法內部發生的異常,這對於調用站點來說是“一勞永逸”的事情。 但是,當您公開Task ,現在可以通過異步等待更好地處理該異常:

public async Task WaitAndThrowAsync()
{
    await Task.Delay(1000);
    throw new Exception("yay");
}

public async Task CallWaitAndThrowAsync()
{
    try
    {
        await WaitAndThrowAsync(); 
    }
    catch (Exception e)
    {
       // Do something. 
    }
}

第三,在第一個示例中,是否可以返回一個數組(字符串)?

是的,通過返回Task<string[]>

public async Task<string> GetArrayAsync()
{
    HttpClient client = new HttpClient();
    var responseStream = await client.GetStreamAsync("http://msdn.microsoft.com");

    using (var streamReader = new StreamReader(responseStream))
    {
        return await streamReader.ReadToEndAsync();
    }
}

當您將方法標記為async ,編譯器將為您隱式創建一個Task 當您具有返回類型時,生成的任務是Task<T> ,其中T是您的返回類型。

第二個例子不是一個很好的例子:由於async void因此不再可能等待異步方法。 async void應該僅用於事件處理程序。

對於第二個問題,是的,可以返回字符串數組。 只需使用Task<string[]>

我真的建議您閱讀Stephen Cleary的這篇出色文章: https : //msdn.microsoft.com/zh-cn/magazine/jj991977.aspx

本文中的一些最佳做法:

  • 避免異步無效:與異步無效方法相比,首選異步任務方法 例外:事件處理程序
  • 一路異步:不要混用阻塞代碼和異步代碼。 例外:控制台主要方法

那一秒不符合Microsoft指定准則

返回類型是以下類型之一:-如果您的方法具有一個返回語句,其中操作數的類型為TResult,則執行任務。 -如果您的方法沒有return語句或沒有操作數的return語句,則執行任務。 -無效(Visual Basic中的Sub),如果您正在編寫異步事件處理程序。

為什么方法應該返回TaskTask<T>

每個返回的任務代表正在進行的工作。 任務封裝有關異步進程狀態的信息,最終封裝有關該進程的最終結果的信息,或者封裝如果該進程不成功則引發的異常的信息。

因此,當您使用void時,您會丟失信息。 您將放棄實際的任務進度和執行信息。 因此,對於void返回類型,請使用Task 對於任何其他類型,請使用Task<T> ,其中T是實際的返回類型。

一些方法可以返回void ,但事件處理程序或啟動程序方法禁止這樣做:

異步方法也可以是Sub方法(Visual Basic)或具有void返回類型(C#)。 此返回類型主要用於定義事件處理程序,其中需要void返回類型。 異步事件處理程序通常用作異步程序的起點。

暫無
暫無

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

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