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.