How to do asynchronous web calls from within asp.net - c#

Lets say im within an ASP.NET application, WCF or web API, part of this applications job to is contact a 3rd party over the way. Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
Here is some code i have written:
public string GetSomeData()
{
Task<string> stuff = CallApiAsync();
return stuff.result; //does this block here?
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
I thought the idea was as follows but please correct any misconceptions.
The caller of CallApi can call the method and when it hits await there is a Task created which represents some work to be done asynchronously but that will take some time. At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request. Once the Task completes the await line wakes up and the code continues from there as if it was synchronous.
If this is the case why do i need to return a Task from my apimethod. The caller seems to have to call stuff.Result which implies that the task may not have finished and calling result could block ? Note i don't want to make the calling method async too as then the method that calls that would need to be async etc etc.
What is the order of event here in my code?
One other question is why did i need to set configureAwait to false? otherwise everything hangs.

Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
That's not possible. In order to be truly asynchronous, you must allow async to "grow" through the code as far as it needs to. What you're trying to do is block on an asynchronous call, which won't give you any benefit (you're freeing up a thread by using async, but then you're turning around and consuming a thread by using Result).
At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request.
Not quite. When an async method hits an await, it returns an incomplete Task to its caller. If the caller, in turn, awaits that task, then it returns an incomplete Task to its caller, etc. When the ASP.NET runtime receives an incomplete Task from your action/service method/whatever, then it releases the thread to the thread pool.
So, you do have to go "async all the way" to see the real benefit of async.
I have an async intro on my blog if you want a more gentle introduction, as well as an MSDN article on async best practices (one of which is: async all the way). I also have a blog post that describes the deadlock you were seeing.

The compiler handles a lot of the magic behind the async pattern for you, but syntactically, you have to tell it what you want it to do by providing a method prototype that says "ok, this is an asynchronous operation that can be awaited."
For this to happen, your method must return a Task or Task<T>.
Any Task can be awaited.
You should be VERY careful when using .Result and .Wait(), as they can block in some very unexpected circumstances, because the runtime may decide to execute your method synchronously.
You should say:
await CallApiAsync();
or, to actually take advantage of it:
Task stuff = CallApiAsync();
//More code that can happen independetly of "stuff"
await stuff;
In order to do that, your GetSomeData() function must also be marked as async, but it doesn't have to, itself, return a Task.
Finished copy of a working async version of your code:
public async string GetSomeData()
{
Task stuff = CallApiAsync();
return await stuff;
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
Honestly, if that's all the CallApiAsync function is ever going to do, you may as well inline it, though.

Related

Call async method synchronously with await

I'm calling an async method (LoginAsync) for Authorization.
UserObject = clienAuthenticationService.LoginAsync(sUser).Result;
if (UserObject != null)
{
// Proceed for further code;
}
else
{
// Show Error message of failed authentication;
}
As this is third party service, I need output of LoginAsync before I go to next line (If block).
Current code is working fine for me and I know it waits until LoginAsync is executed.
However, I'm getting recommendation to Replace this use of 'Task.Result' with 'await'.
Question : I'm not sure if my case is relevant for await, since I need kind of Synchronous execution of async method. Can someone please confirm if recommendation given to me is irrelevant in my case or there is way to call async method synchronously with await ?
EDIT : After comments, I modified my code to add await instead of .Result. Still, unable to read response from async method. Below is new code
public static async Task<bool> CallJimService(LoginUserClass sUser)
{
var result = clientJIMServiceCall.LoginAsync(sUser).ConfigureAwait(false);
LoginUserClass loginUserDetails = await result;
if (loginUserDetails != null && loginUserDetails.UserProperties != null && loginUserDetails.UserProperties.LoggedIn)
{
return true;
}
else
{
return false;
}
}
public static Boolean ValidateUserCredentails(string pstrUserName, string pstrPassWord)
{
LoginUserClass sUser = new LoginUserClass();
sUser.UserName = pstrUserName;
sUser.Password = pstrPassWord;
return CallJimService(sUser).Result; // Here I want to avoid using .Result.
}
Also, I don't want to change ValidateUserCredentails() to async. How Can I get through this?
The LoginAsync method is marked async, and returns a Task. This method is expected to have an asynchronous implementation. You cannot execute this method synchronously, because this method does not have a synchronous implementation. If the class you are using would provide a synchronous implementation of the Login operation, they would have to expose a Login method.
There is no guarantee that calling this method asynchronously will result in an asynchronous operation. Asynchronous methods may return synchronously if the state needs them to. For instance, AsyncLogin may return synchronously if you already have logged in. However, unless doing something extremely specific, there must be at least one execution path in the method that requires some asynchronous operation.
Recommendation given to you is not irrelevant.
You should not block on an async operation, especially using Task.Result. Asynchronous operations does not involve multithreading, and awaiting on a Task.Result may provoke a deadlock of your application, because your thread will be waiting on the Result and will not be able to respond to the async operation signaling completion.
You'd rather await the LoginAsync method asynchronously, making your method async as well.
If you are forced to call the LoginAsync method from a synchronous context, the correct implementation will depend on what exactly you are trying to achieve and what the LoginAsync method does.
If you are able to use await (that is if you are in an async method already), then use await.
UserObject = await clienAuthenticationService.LoginAsync(sUser);
Using await helps the code run synchronous(that is it preserves flow of control).
I will try to explain async usage through the following example, which has asynchronous execution flow, but synchronous control flow -
Following code runs out of sync (asynchronous that is) -
// Authenticate the user, but don't wait here while authenticating.
// Async part could be - Checking database for user details. (Network IO operation)
var UserAuthTask = LoginAsync();
// Prepare a layout or something to show when authentication fails. Don't show yet.
// Again, don't wait while preparing.
// Async part could be - Reading a render template file. (File IO operation)
var AuthFailScreen = PrepareFailScreenAsync();
// Similar to failure screen.
var AuthSuccessScreen = PrepareSuccessScreenAsync();
Now, we use await to synchronize the flow to our liking -
var UserAuthResult = await UserAuthTask;
if (UserAuthResult.Success)
{
var SuccessScreen = await AuthSuccessScreen;
SuccessScreen.Show();
}
else
{
var FailScreen = await AuthFailScreen;
FailScreen.Show();
}
You could await each of the tasks before, like var UserAuthTask = await LoginAsync();, but then you would lose the benefit of doing multiple things which could've been done while authenticating.
I am not sure about exception handling, but mix and match of async and sync code will likely cause issues.
Please correct me if I am wrong at any point. Thanks.

Should I add the async modifier if I return a Task in an expensive method?

The C# compiler already warns us if we have a method that has the async modifier but does not use the await operator.
According to this answer there's no point adding an await to the end of an async method (and in that case, just remove the async modifier).
But what if the method has an expensive synchronous operation it needs to perform before calling a subsequent true async method?
For example, if I'm using HttpClient:
private readonly HttpClient client = ...
public Task<HttpResponseMessage> CallMyWebServiceMethod() {
HttpRequestMessage request = this.SomeExpensiveButSynchronousMethod();
return this.client.SendAsync( request );
}
This code would block the caller (due to SomeExpensiveButSynchronousMethod).
However, if I change the code to this:
public async Task<HttpResponseMessage> CallMyWebServiceMethod() {
HttpRequestMessage request = this.SomeExpensiveButSynchronousMethod();
return await this.client.SendAsync( request );
}
and I call it like so:
HttpResponse response = await myWrapper.CallMyWebServiceMethod();
...I understand the TPL would spin up a background thread immediately and then run CallMyWebServiceMethod in the background thread, resuming whatever the parent code wants, making the entire call non-blocking in the process, before resuming after the Task completes and returns the HttpResponse.
...if that's the case then it seems contradictory.
If I'm wrong, and the call is blocking until it gets to SendAsync then how can I execute SomeExpensiveButSynchronousMethod on the same background thread as the HttpClient uses for its request?
According to this answer there's no point adding an await to the end of an async method (and in that case, just remove the async modifier).
That's an oversimplification. See my blog post on eliding async and await.
But what if the method has an expensive synchronous operation it needs to perform before calling a subsequent true async method?
This is a rare case, but the appropriate solution IMO is to execute the synchronous operation synchronously (i.e., not wrapped in a Task.Run) and be sure to document its behavior.
I understand the TPL would spin up a background thread immediately and then run CallMyWebServiceMethod in the background thread, resuming whatever the parent code wants, making the entire call non-blocking in the process, before resuming after the Task completes and returns the HttpResponse.
That is not at all what happens. You may find my async intro helpful. Quote:
The beginning of an async method is executed just like any other method. That is, it runs synchronously until it hits an “await” (or throws an exception).
In actuality, both of your examples synchronously block the caller while executing SomeExpensiveButSynchronousMethod.
If I'm wrong, and the call is blocking until it gets to SendAsync then how can I execute SomeExpensiveButSynchronousMethod on the same background thread as the HttpClient uses for its request?
HttpClient doesn't use a background thread for its request, so this part of the question doesn't make sense. For more information on how asynchronous I/O works, see my blog post There Is No Thread.
To answer the actual question:
Should I add the async modifier if I return a Task in an expensive method?
Yes. But the reason you should do so is not to "make it asynchronous"; it's so that any exceptions from SomeExpensiveButSynchronousMethod are captured and placed on the returned Task, which is the expected semantic for methods that follow the Task-based Asynchronous Pattern (TAP).
I understand the TPL would spin up a background thread immediately and then run CallMyWebServiceMethod
No, that's not what happens. The first synchronous part of an async method executes synchronously. If you want make sure it does not block the current thread, you should use Task.Run().
Your expensive method is going to block the caller either way. async doesn't magically create threads for you, that's what Task does (sometimes). So, if you add async and await the SendAsync, you're just adding state-machine overhead needlessly.
see also http://blog.stephencleary.com/2016/12/eliding-async-await.html

how and when to fetch return from awaitable(async) method

I am pretty sure, this was answered already and I read many related stuff but somehow I am not getting it to work in my code. Here is the exact code base.
I have this async method in my library, that returns a string upon doing some DB entries:
public class MyLibrary
{
public async Task<string> DoSomethingAsync()
{
return await DoAsync();
}
// some private method, with multiple parameters
private Task<string> DoAsync()
{
return Task.Run(() => Do());
}
}
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
console.Write(myTask.Result);
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it? Or since the call is running on another thread, the task might not yet completed when my cursor hits the line 2. So what now? the cursor will wait till the task gets completed or the line 2 gets executed whenever the task gets completed? sounds synchronous to me..
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that? some posts, suggested in doing like below, which gave me the result, but created some more confusion:
var myTask = Task.Run(async () => await MyLibraryobject.DoSomethingAsync());
myTask.Wait();
console.Write(myTask.Result);
What is happening above? why should i create another task and set it to wait? can't I wait for the thread, used by the async method? Again, i am clearly missing some basic stuff here.
Lastly, this is an async call, but the UI thread is waiting for it to be completed thus gives me an impression that it's synchronous. Am I thinking it right? Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Also what's the difference between a fire-and-forget call being non-async and async? is there any benefit of returning Task, instead of void, for such calls?
I am pretty sure, some broken link that connects all these pieces together in my brain. Can someone explain that to me, please??
You should probably start with my async intro and follow up with my article on async best practices. They answer almost all your questions.
For the details...
how and when to fetch return from awaitable(async) method
You should use await to get the result from an async task.
I have this async method in my library, that returns a string upon doing some DB entries
Then it should not be using Task.Run. It should be using naturally-asynchronous APIs, e.g., Entity Framework's FirstAsync.
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it?
No. The UI is blocking because your code is calling Result. Result is a blocking call.
sounds synchronous to me..
That's because you're making it synchronous by using Result. If you use await, the code will execute serially, but asynchronously.
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that?
Your code is already doing that. It's explicitly blocking until the task is complete. If you change it to properly use await, it will be explicitly waiting (but not blocking) until the task is complete.
some posts, suggested in doing like below
No. Don't use Task.Run unnecessarily.
can't I wait for the thread, used by the async method?
Pure async methods don't have threads that they use.
Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Async makes sense when it's consumed with await.
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
This is blocking the UI because it is not awaited. You simply need to await an async method
string res = await MyLibraryobject.DoSomethingAsync();
and the above should be placed in the UI inside an async context too.
Edit - reply to comment do "you mean another wrapper async method, which returns Task<string>..."? No,I don't. When I wrote "inside an async context" I meant to add the async keyword to a subscribed event, like a button click, if you are in the code behind or to your delegate command implementation, if you are in a more advanced MVVM implementation of the GUI.
Furthermore, your class library is supposed to do something truly asynchronous, not just starting a task and wrapping it inside a formally async method, like it is your DoAsync.
Edit - in reply to comment "how should avoid" it? If you can't do async all the way, just keep the library and the API sync and unblock the UI by starting a separate thread to call the sync api.

Is there any benefit in using await with an async method without intermediate work?

MSDN uses the below example:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
So the GetStringAsync method will basicallly promise to return a Task of type string at some point in the future, but by the time DoIndependentWork is called, getString hasn't been awaited yet so it can continue to do other work until this happens.
But the documentation then says
If AccessTheWebAsync doesn't have any work that it can do between
calling GetStringAsync and awaiting its completion, you can simplify
your code by calling and awaiting in the following single statement.
string urlContents = await client.GetStringAsync();
Is there any benefit to doing this at all if you're just going to await something straight away? Or is it just so you're preparing in advance to use asynchrony as your applications develops?
The main advantage is that await <some-operation-that-does-I/O> doesn't tie up a thread in a wait, improving resource utilization. A thread will only be commissioned when the I/O completes. You can have many more outstanding I/O requests on a system than you can have waiting threads. Stephen Cleary has an article on this that explains it more eloquently than I can.
The designer of an awaitable async method, thought that chances are high that somewhere during execution of the method he would have to wait for something to complete.
Instead of a busy wait, he gives you the possibility to do "something else" until you either need the result of the method or have nothing to do anymore.
It might be that you have no "something else" to do but your caller might or his caller. Even if no one has something else to do, using the async give the operator the opportunity to start something else, for instance minimize the window. We call this "keep the UI responsive".
So the answer is: yes, even if you have nothing to do and just await anyAsyncFunction(), it is meaningful to be an async function yourself whenever you call any other async function.

C# await / async in WebApi, what's the point?

Does anybody know what is the purpose of doing this?
private async Task<bool> StoreAsync(TriviaAnswer answer) { ... }
[ResponseType(typeof(TriviaAnswer))]
public async Task<IHttpActionResult> Post(TriviaAnswer answer)
{
var isCorrect = await StoreAsync(answer);
return Ok<bool>(isCorrect);
}
From examining this, it is telling it to run the private method asynchronously but synchronously wait for it to end. My question is, is there any point to this? Or is this just a fancy yet futile technique? I ran into this while studying some code for Web API / MVC / SPA.
Anyway, any insights would be useful.
Despite its name, await doesn't actually work like Thread.Join. async and await are Microsoft's implementation of coroutines, implemented using a Continuation Passing Style. Work is reordered so that processing can continue while the Task<T> is being completed. Instructions are re-arranged by the compiler to make maximum use of the asynchronous operation.
This article explains it thusly:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
For some trivial code examples, await doesn't really make much sense, because there is no other work that you can do in the meantime while you are awaiting.

Categories

Resources