简体   繁体   English

在 C# 中使用异步和等待

[英]Using Async and Await in C#

I'm trying to understand async and await, and I've got a few questions.我正在尝试了解 async 和 await,但我有几个问题。 In this example from Microsoft微软的这个例子中

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;
}
  1. The method uses client.GetStringAsync , however, what happens if the method you're calling isn't an Async method?该方法使用client.GetStringAsync ,但是,如果您调用的方法不是 Async 方法,会发生什么情况? If I were calling for example, File.ReadAllLines() , how would I make that an Async call?例如,如果我正在调用File.ReadAllLines() ,我将如何进行异步调用?

  2. The method has a return type of Task<int> .该方法的返回类型为Task<int> Does any method that uses await, have to have a return type of Task<> ?是否有任何使用 await 的方法必须具有Task<>的返回类型? What if there is nothing to return?如果没有什么可以返回怎么办?

  1. You would call the appropriate Async method.您将调用适当的 Async 方法。 If there isn't one, then it won't be truly asynchronous.如果没有,那么它就不会是真正的异步。 You could "make" your own by wrapping it with Task.Run() but it really defeats the purpose of being async.你可以通过用 Task.Run() 包装它来“制作”你自己的,但它确实违背了异步的目的。 This is fine in a desktop app, but it's a terrible idea to do in an ASP.NET/server scenario because you're creating more threads to handle the same functionality.这在桌面应用程序中很好,但在 ASP.NET/服务器场景中这样做是一个糟糕的主意,因为您要创建更多线程来处理相同的功能。 (Too many threads means your throughput will suffer in server scenarios). (太多线程意味着您的吞吐量将在服务器场景中受到影响)。 All I/O (database ,file access) in .NET should have the appropriate Async() methods along with the standard blocking methods. .NET 中的所有 I/O(数据库、文件访问)都应该具有适当的 Async() 方法以及标准的阻塞方法。 For a deeper discussion on why this is a bad idea, see Stephen Taub's blog post on it .有关为什么这是一个坏主意的更深入的讨论, 请参阅 Stephen Taub 的博客文章

  2. Any method using the async/await pattern has to return a Task<>.任何使用 async/await 模式的方法都必须返回一个 Task<>。 This is because while the system is "await'ing", it will return a Task<>, which represents a future promise of the return type.这是因为当系统在“等待”时,它会返回一个 Task<>,它代表返回类型的未来承诺。 The calling method can continue on if it wishes to other code, or it can stay await'ing your async method call and provide scalability benefits until the true underlying type has been returned from that async method.如果它希望其他代码,调用方法可以继续,或者它可以等待您的异步方法调用并提供可伸缩性优势,直到真正的底层类型从该异步方法返回。

The method uses client.GetStringAsync, however, what happens if the method you're calling isn't an Async method?该方法使用 client.GetStringAsync,但是,如果您调用的方法不是 Async 方法,会发生什么情况? If I were calling for example, File.ReadAllLines(), how would I make that an Async call?例如,如果我调用 File.ReadAllLines(),我将如何进行异步调用?

Don't drive async from the "outside in";不要从“外在”驱动async rather, let it bubble up from the "inside out".相反,让它从“由内而外”冒泡。 In other words, if you want to make something asynchronous, you first find the lowest-level APIs that are asynchronous, then you make the calling method async .换句话说,如果你想实现异步,你首先要找到异步的最低级别的 API,然后你将调用方法async

The method has a return type of Task.该方法的返回类型为 Task。 Does any method that uses await, have to have a return type of Task<>?是否有任何使用 await 的方法必须具有 Task<> 的返回类型? What if there is nothing to return?如果没有什么可以返回怎么办?

Then the result type of the method should be Task .那么该方法的结果类型应该是Task

Technically, async methods can return Task , Task<T> , or void .从技术上讲, async方法可以返回TaskTask<T>void You should avoid async void ;你应该避免async void it should only be used for event handlers (or methods that are logically event handlers).它应该只用于事件处理程序(或逻辑上是事件处理程序的方法)。 Task<T> is a wrapper around a result type of T ; Task<T>是围绕一个结果类型的包装T ; this wrapper also includes information about any exceptions.此包装器还包括有关任何异常的信息。 Similarly, Task contains valuable information about exceptions (or successful completion).同样, Task包含有关异常(或成功完成)的宝贵信息。

If I were calling for example, File.ReadAllLines(), how would I make that an Async call?例如,如果我调用 File.ReadAllLines(),我将如何进行异步调用?

You don't "make something" async, it has to be naturally so.你不会“做某事”异步,它必须是自然的。 Many operations are IO bound, such as a network call or accessing disk.许多操作都是 IO 绑定的,例如网络调用或访问磁盘。 There is no File.ReadAllLinesAsync , but you can write one yourself using a "lower-level" API such as FileStream .没有File.ReadAllLinesAsync ,但您可以使用“低级”API(例如FileStream自己编写一个。

Does any method that uses await, have to have a return type of Task<>?是否有任何使用 await 的方法必须具有 Task<> 的返回类型? What if there is nothing to return?如果没有什么可以返回怎么办?

No, it doesn't.不,它没有。 A Task<T> is used when you have a return value from an asynchronous method.当您有来自异步方法的返回值时,将使用Task<T> In your example, that value is a string .在您的示例中,该值是一个string It is wrapped in a Task<> because a Task is a promise of work which will complete in the future.它被包装在一个Task<>因为Task是对未来将完成的工作的承诺。 Awaiting on a Task<string> asynchronously waits until the async operation is done and that string is returned.异步等待Task<string>直到异步操作完成并返回该string

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM