Asp.Net Core Asynchronous programming

Recently, I encountered an asynchronous problem when writing the APIs of Asp.Net Core, and I really felt unexpected after solving it, so I wrote it down and shared it with you, and avoid encountering it later.

What is Asynchronous

Before explaining what is asynchronous, let everyone know what the definition of synchronization is, simply put, a task is done continuously, and the next task will not be done before the previous task is done, as shown in the following figure.

flowchart LR
A(TASK A) --> B(TASK B)-->C(TASK C) --> D(TASK D) --> E(TASK E)

As for async, it is possible to have multiple tasks at the same time, and there is no need to wait because the simultaneous tasks have not yet completed, as shown in the following figure.

flowchart LR
A(TASK A) --> B(TASK B)
C(TASK C) --> D(TASK D) --> E(TASK E)
F(TASK F) --> G(TASK G)

So what programming I happen

The problem is that when a highly concurrent request is encountered, the APIs are timed out to respond to the request.
After some modifications and cross-comparisons, it was found that the synchronized writing API encountered the need to communicate with other APIs, and if it was high concurrency, it would cause our APIs to no longer respond.
Then there is the fact that when the asynchronous writing is wrong, it will also cause a serious timeout condition, so I will explain it further.

Asp.Net Core Asynchronous

After the .Net Framework 4.5 there is more async and await keyword, just declare async before you want to pass back the value as an asynchronous method and with Task<T> to complete the asynchronous method, then use await before calling the method to synchronously wait for the result, and do not add the await keyword if you do not need to wait. The complete example is as follows.

    public async Task<IEnumerable<string>> GetStringAsync()
    {
        await Task.Delay(TimeSpan.FromSeconds(10));
        return new string[]{"First", "Second", "Third"};
    }

Problem I have

If you write before from the .Net Framework 4.5, and need the synchronous syntax to high concurrency requests or complex operations or communicate with other APIs. Then the synchronous API cannot use the await keyword when calling to the asynchronous syntax, so it can only use the Task.Result method to call, as shown in the following figure.

    [HttpGet("Result")]
    public IEnumerable<string> GetResult()
    {
        return _service.GetStringAsync().Result;
    }

However, the synchronous syntax encounters a high concurrency request will cause a response timeout situation, so the asynchronous syntax will be used to rewrite, but simply adding async and work with Task.Result will still cause a blocking situation, which is crawling to see MSDN asynchronous programming to know that there is such a result, so the following writing method will still cause the request to block the situation.

    [HttpGet("Result")]
    public async Task<IEnumerable<string>> GetResult()
    {
        return _service.GetStringAsync().Result;
    }

So how to write is the right way to write?

Correct writing

So in summary, to write an asynchronous API, you basically need to use the keyword async first, and then use the return value of Task<T> or Task for whether there is a callback value or no need return value, as shown below.

    [HttpGet("String")]
    public async Task<IEnumerable<string>> GetString()
    {
        await Task.Delay(TimeSpan.FromSeconds(10));
        return new string[]{"First", "Second", "Third"};
    }

In addition, when encountering a method that needs to be blocked, that is, when encountering a method that needs to wait for the result of another method, use the keyword await, as shown below,

    [HttpGet("Result")]
    public async Task<IEnumerable<string>> GetResult()
    {
        return await _service.GetStringAsync();
    }

Be careful not to use a way of writing Task.Result here, otherwise the reaction time of the run will be greatly reduced.

Result

Whether it’s written synchronously or in the asynchronous API call Task.Result, the result when a highly concurrent call of 100 times per second is encountered will react with a delay of more than five seconds, and only the async/await can react normally within three seconds.

Conclusion

After this experience, when writing APIs, first write async, so as to avoid the dilemma that the api’s reaction is blocked when high concurrency is blocked. Then the asynchronous’ writing method must be written with aync and await, avoiding the writing of Task.Result, so as to avoid the occurrence of blocking.

Reference

  1. MSDN Asynchronous programming

Leave a Reply

Your email address will not be published. Required fields are marked *