简体   繁体   English

使用异步/等待 - C#

[英]using async/await - c#

I have the following code.我有以下代码。 What exactly does the code do?代码究竟做了什么? Why do we need the Stopwatch , XmlSerializer , MemoryStream .为什么我们需要StopwatchXmlSerializerMemoryStream Is there are simpler way of doing it using async/await ?是否有使用async/await更简单的方法? Also does using contentResponse.Result;也使用contentResponse.Result; lead to a deadlock situation always.总是导致僵局。

    public T GetResponse<T>()
    {
        var response = default(T);

            using (HttpClient httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);

                Stopwatch watch = Stopwatch.StartNew();

                var contentResponse = httpClient.GetAsync(uri.ToString());

                try
                {
                    contentResponse.Wait();
                }
                catch (Exception exception)
                {

                }

                var wsResponseContent = contentResponse.Result;
                wsResponseContent.Content.LoadIntoBufferAsync();
                var resultTask = wsResponseContent.Content.ReadAsStringAsync();
                resultTask.Wait();

                string wsResponseContentText = resultTask.Result;

                if (watch.IsRunning)
                    watch.Stop();

                wsResponseContent.EnsureSuccessStatusCode();
                if (wsResponseContent.IsSuccessStatusCode)
                {
                    XmlSerializer result = new XmlSerializer(typeof(T));

                    using (MemoryStream sresultStream = new MemoryStream(Encoding.UTF8.GetBytes(wsResponseContentText)))
                    {
                        response = (T)result.Deserialize(sresultStream);
                        sresultStream.Close();
                    }
                }
            }
       
        return response;
    }

There is no need for the StopWatch in this code.此代码中不需要 StopWatch。 Usually used as a diagnostic tool, it can be useful.通常用作诊断工具,它很有用。 But not in this instance.但不是在这种情况下。 From the code below it seems that it reads a string send over the web and tries to read it as an XML format.从下面的代码看来,它读取通过网络发送的字符串并尝试将其读取为 XML 格式。 Thus the need for the MemoryStream and XMLSerializer .因此需要MemoryStreamXMLSerializer

As for your deadlock situation.至于你的死锁情况。 It is always because two instances is trying to access the same instance.这总是因为两个实例试图访问同一个实例。 You can avoid this by await your functions properyly.您可以通过适当地等待您的功能来避免这种情况。 If oyu really want a proper async implement the function as follow:如果 oyu 真的想要一个合适的async实现如下功能:

public async Task<T> GetResponse<T>()
{
    var response = default(T);

    using (HttpClient httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);

        var contentResponse = await httpClient.GetAsync(uri.ToString());

        await wsResponseContent.Content.LoadIntoBufferAsync();
        var wsResponseContentText = await wsResponseContent.Content.ReadAsStringAsync();

        wsResponseContent.EnsureSuccessStatusCode();
        
        if (wsResponseContent.IsSuccessStatusCode)
        {
            XmlSerializer result = new XmlSerializer(typeof(T));

            using (MemoryStream sresultStream = new MemoryStream(Encoding.UTF8.GetBytes(wsResponseContentText)))
            {
                response = (T)result.Deserialize(sresultStream);
                sresultStream.Close();
             }
        }
    }
   
    return response;
}

In the above code if a function has async in it.在上面的代码中,如果函数中有async We can await the result instead of the task.我们可以等待结果而不是任务。 For example in the code below:例如在下面的代码中:

public async Task<int> GetNumber5Async() {
    return 5;
}

If we are to call it like you did before:如果我们像您之前那样称呼它:

var number5 = GetNumber5Async(); // Returns Task<int>

We will receive back a Task we will need to get the results from.我们将收到一个我们需要从中获取结果的任务。 However, if we immediately await the Task:但是,如果我们立即等待任务:

var number5 = await GetNumber5Async(); // Returns 5

We immedaitely get the result back and don't have to do number5.Wait(); number5.result;我们立即得到结果,而不必执行number5.Wait(); number5.result; number5.Wait(); number5.result;


Turtles all the way Down海龟一路下来

One thing you will need know when working with Async Methods is the concept of 'Turtes all the way Down'.使用异步方法时您需要了解的一件事是“Turtes all the way Down”的概念。 Simply what it says is if you have a async method anywhere, all your methods call it and calling those methods needs to be async as well.简单地说就是如果你在任何地方都有一个异步方法,你所有的方法都会调用它并且调用这些方法也需要异步。 So what is needed for a method to be async?那么异步方法需要什么?

  1. In requires to be a Task . In 需要是一个Task So instead of returning a value, it will need to return a Task with a value encapsulated.因此,它需要返回一个封装了值的Task ,而不是返回一个值。

For example:例如:

// None Async
public int GetNumber5() { return 5;} 

// Async
public async Task<int> GetNumber5Async() { return 5; }
  1. Requires the async descriptor to both use and call o be able to await a function.需要async描述符才能使用和调用 o 才能await函数。

For example:例如:

// None Async
void GetANumber(){
    var num5 = GetNumber5();
}

// Async
async void GetANumber(){
    var num5 = await GetNumber5Async();
}

Avoiding Deadlocks with Async使用异步避免死锁

Usually awaiting a function is engough.通常等待一个函数就足够了。 But if it still creates deadlocks you can add '.ConfigureAwait(false);'但如果它仍然造成死锁,你可以添加 '.ConfigureAwait(false);'

For Example:例如:

var num5 = await GetNumber5Async().ConfigureAwait(false);

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

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