简体   繁体   English

消除异步和等待流程

[英]Eliding async and await flow

In the article about eliding async await , there is an example as follows:在关于省略 async await的文章中,有一个例子如下:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using (var client = new HttpClient())
        return client.GetStringAsync(url);
}

And he described the flow as follows:他将流程描述如下:

With GetElidingKeywordsAsync, the code does this:使用 GetElidingKeywordsAsync,代码执行以下操作:

  1. Create the HttpClient object.创建 HttpClient object。

  2. Invoke GetStringAsync, which returns an incomplete task.调用 GetStringAsync,它返回一个不完整的任务。

  3. Disposes the HttpClient object.处理 HttpClient object。

  4. Returns the task that was returned from GetStringAsync.返回从 GetStringAsync 返回的任务。

Why isn't the flow as follows?为什么流程不如下?

  1. Create the HttpClient object.创建 HttpClient object。

  2. Disposes the HttpClient object.处理 HttpClient object。

  3. Invokes the GetStringAsync, and returns the task that was returned from GetStringAsync.调用 GetStringAsync,并返回从 GetStringAsync 返回的任务。

A using block without curly braces or semi-colon has an implied body:没有花括号或分号的 using 块有一个隐含的主体:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using (var client = new HttpClient())
        return client.GetStringAsync(url); // using body
}

This can be normalized to:这可以归一化为:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using (var client = new HttpClient())
    {
        return client.GetStringAsync(url);
    }
}

Or written more compactly in C#8.0:或者用 C#8.0 更紧凑地编写:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using var client = new HttpClient();
    return client.GetStringAsync(url);
}

If you add a semi-colon, there would be an empty body, yielding the behavior you describe in OP:如果添加分号,则会出现一个空正文,从而产生您在 OP 中描述的行为:

public Task<string> GetElidingKeywordsAsync(string url)
{
    HttpClient client;
    using (client = new HttpClient());  // gets disposed before next statement
        return client.GetStringAsync(url);  // don't be fooled by the indent
}

This can be normalized to:这可以归一化为:

public Task<string> GetElidingKeywordsAsync(string url)
{
    HttpClient client;
    using (client = new HttpClient())
    {
    }
    return client.GetStringAsync(url);
}

Expanding on the comment given above, it would help if you see how the GetStringAsync method works.扩展上面给出的评论,如果您了解GetStringAsync方法的工作原理,将会有所帮助。

Assuming the following to be the aysnc method:假设以下是 aysnc 方法:

public async Task<string> GetMethodAsync(string url)
{
    // perform some operations

    // execution will pause here due to await statement 
    // after calling download URL and the Task will be returned
    var result = await DownloadURL(string);

    //perform some more function
    // finally return the result
    return result;
}

Note here the method call to DownloadURL will be executed and then only the execution will pause to wait for results to come back, and a task is returned.注意这里会执行对DownloadURL的方法调用,然后只会暂停执行以等待结果返回,并返回一个task Making a method Async does not in itself give you deferred execution, only the part after the await call gets "deferred".制作方法 Async 本身并不会给您延迟执行,只有 await 调用之后的部分会被“延迟”。

That is the reason you will get an incomplete task and then in next step the client gets disposed.这就是你会得到一个不完整的任务然后在下一步中客户被处理的原因。

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

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