async Task<HttpResponseMessage> Get VS HttpResponseMessage Get - c#

I would need your help in the following. For nearly a month, I have been reading regarding Tasks and async .
I wanted to try to implement my new acquired knowledege, in a simple wep api project. I have the following methods and both of them working as expected:
public HttpResponseMessage Get()
{
var data = _userServices.GetUsers();
return Request.CreateResponse(HttpStatusCode.OK, data);
}
public async Task<HttpResponseMessage> Get()
{
var data = _userServices.GetUsers();
return await Task<HttpResponseMessage>.Factory.StartNew(() =>
{
return Request.CreateResponse(HttpStatusCode.OK, data);
});
}
So the question. I have tried to use fiddler and see what is the difference between these two. The async one is little faster, but apart from that, what is the real benefit in implementing something like that in a web api?

As others have pointed out, the point of async on ASP.NET is that it frees up one of the ASP.NET thread pool threads. This works great for naturally-asynchronous operations such as I/O-bound operations because that's one less thread on the server (there is no thread that is "processing" the async operation, as I explain on my blog). Thus, the primary benefit of async on the server side is scalability.
However, you want to avoid Task.Run (and, even worse, Task.Factory.StartNew) on ASP.NET. I call this "fake asynchrony" because they're just doing synchronous/blocking work on a thread pool thread. They're useful in UI apps where you want to push work off the UI thread so the UI remains responsive, but they should (almost) never be used on ASP.NET or other server apps.
Using Task.Run or Task.Factory.StartNew on ASP.NET will actually decrease your scalability. They will cause some unnecessary thread switches. For longer-running operations, you could end up throwing off the ASP.NET thread pool heuristics, causing additional threads to be created and later destroyed needlessly. I explore these performance problems step-by-step in another blog post.
So, you need to think about what each action is doing, and whether any of that should be async. If it should, then that action should be async. In your case:
public HttpResponseMessage Get()
{
var data = _userServices.GetUsers();
return Request.CreateResponse(HttpStatusCode.OK, data);
}
What exactly is Request.CreateResponse doing? It's just creating response object. That's it - just a fancy new. There's no I/O going on there, and it certainly isn't something that needs to be pushed off to a background thread.
However, GetUsers is much more interesting. That sounds more like a data read, which is I/O-based. If your backend can scale (e.g., Azure SQL / Tables / etc), then you should look at making that async first, and once your service is exposing a GetUsersAsync, then this action could become async too:
public async Task<HttpResponseMessage> Get()
{
var data = await _userServices.GetUsersAsync();
return Request.CreateResponse(HttpStatusCode.OK, data);
}

Using async on your server can dramatically improve scalability as it frees up the thread serving the request to handle other requests while the async operation is in progress. For example in a synchronous IO operaton, the thread would be suspended and doing nothing until the operation completes and would not be available to serve another request.
That being said, using Task.Factory.StartNew starts another thread so you don't get the scalability benefits at all. Your original thread can be reused, but you have offloaded the work to another thread so there is no net benefit at all. in fact there is a cost of switching to another thread, but that is minimal.
Truly asynchronous operations do not start a thread and I would look to see if such an operation exists, or if one can be written for Request.CreateResponse. Then your code would be much more scalable. If not, you are better off sticking with the synchronous approach.

It makes more sense where the call is happening with major IO operations.
Yes, Async is faster because it frees up the request thread for the time that the operations is being performed. Thus, from Web server point of view, you are giving a thread back to the pool that can be used by the server for any future calls coming through.
So for e.g. when you are performing a search operation on SQL server, you might want to do async and see the performance benefit.
It is good for scalability that involves multiple servers.
So, for e.g. when the SearchRecordAsync sends its SQL to the database, it returns an incomplete task, and when the request hits the await, it returns the request thread to the thread pool. Later, when the DB operation completes, a request thread is taken from the thread pool and used to continue the request.
Even if you are not using, SQL operations, let say you want to send an email to 10 people. In this case also async makes more sense.
Async is also very handy to show the progress of long event. So user will still get the active GUI, while the task is running at the background.
To understand, please have a look at this sample.
Here I am trying to initiate task called send mail. Interim I want to update database, while the background is performing send mail task.
Once the database update has happened, it is waiting for the send mail task to be completed. However, with this approach it is quite clear that I can run task at the background and still proceed with original (main) thread.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Console.WriteLine("Starting Send Mail Async Task");
Task task = new Task(SendMessage);
task.Start();
Console.WriteLine("Update Database");
UpdateDatabase();
while (true)
{
// dummy wait for background send mail.
if (task.Status == TaskStatus.RanToCompletion)
{
break;
}
}
}
public static async void SendMessage()
{
// Calls to TaskOfTResult_MethodAsync
Task<bool> returnedTaskTResult = MailSenderAsync();
bool result = await returnedTaskTResult;
if (result)
{
UpdateDatabase();
}
Console.WriteLine("Mail Sent!");
}
private static void UpdateDatabase()
{
for (var i = 1; i < 1000; i++) ;
Console.WriteLine("Database Updated!");
}
private static async Task<bool> MailSenderAsync()
{
Console.WriteLine("Send Mail Start.");
for (var i = 1; i < 1000000000; i++) ;
return true;
}
}

Related

Why async controller method is executing just like a sync method?

I've created sample .NET Core WebApi application to test how async methods can increase the throughput. App is hosted on IIS 10.
Here is a code of my controller:
[HttpGet("sync")]
public IEnumerable<string> Get()
{
return this.GetValues().Result;
}
[HttpGet("async")]
public async Task<IEnumerable<string>> GetAsync()
{
return await this.GetValues();
}
[HttpGet("isresponding")]
public Task<bool> IsResponding()
{
return Task.FromResult(true);
}
private async Task<IEnumerable<string>> GetValues()
{
await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
return new string[] { "value1", "value2" };
}
there are methods:
Get() - to get result synchronously
GetAsync() - to get result asynchronously.
IsResponding() - to check that server can serve requests
Then I created sample console app, which creates 100 requests to sync and async method (no waiting for result) of the controller. Then I call method IsResponding() to check whether server is available.
Console app code is:
using (var httpClient = new HttpClient())
{
var methodUrl = $"http://localhost:50001/api/values/{apiMethod}";
Console.WriteLine($"Executing {methodUrl}");
//var result1 = httpClient.GetAsync($"http://localhost:50001/api/values/{apiMethod}").Result.Content.ReadAsStringAsync().Result;
Parallel.For(0, 100, ((i, state) =>
{
httpClient.GetAsync(methodUrl);
}));
var sw = Stopwatch.StartNew();
var isAlive = httpClient.GetAsync($"http://localhost:50001/api/values/isresponding").Result.Content;
Console.WriteLine($"{sw.Elapsed.TotalSeconds} sec.");
Console.ReadKey();
}
where {apiMethod} is "sync" or "async", depending on user input.
In both cases server is not responding for a long time (about 40 sec).
I expexted that in async case server should continue serving requests fast, but it doesn't.
UPDATE 1:
I've changed client code like this:
Parallel.For(0, 10000, ((i, state) =>
{
var httpClient = new HttpClient();
httpClient.GetAsync($"http://localhost:50001/api/values/{apiMethod}");
}));
using (var httpClient = new HttpClient())
{
var sw = Stopwatch.StartNew();
// this method should evaluate fast when we called async version and should evaluate slowly when we called sync method (due to busy threads ThreadPool)
var isAlive = httpClient.GetAsync($"http://localhost:50001/api/values/isresponding").Result.Content;
Console.WriteLine($"{sw.Elapsed.TotalSeconds} sec.");
}
and calling IsResponding() method executing for a very long time.
UPDATE 2
Yes, I know how async methods work. Yes, I know how to use HttpClient. It's just a sample to prove theory.
UPDATE 3
As it mentioned by StuartLC in one of the comments, IIS somehow throtling or blocking requests. When I started my WebApi as SelfHosted it started working as expected:
Executing time of "isresponsible" method after bunch of requests to ASYNC method is very fast, at about 0.02 sec.
Executing time of "isresponsible" method after bunch of requests to SYNC method is very slow, at about 35 sec.
You don't seem to understand async. It doesn't make the response return faster. The response cannot be returned until everything the action is doing is complete, async or not. If anything, async is actually slower, if only slightly, because there's additional overhead involved in asynchronous processing not necessary for synchronous processing.
What async does do is potentially allow the active thread servicing the request to be returned to the pool to service other requests. In other words, async is about scale, not performance. You'll only see benefits when your server is slammed with requests. Then, when incoming requests would normally have been queued sync, you'll process additional requests from some of the async tasks forfeiting their threads to the cause. Additionally, there is no guarantee that the thread will be freed at all. If the async task completes immediately or near immediately, the thread will be held, just as with sync.
EDIT
You should also realize that IIS Express is single-threaded. As such, it's not a good guage for performance tuning. If you're running 1000 simultaneous requests, 999 are instantly queued. Then, you're not doing any asynchronous work - just returning a completed task. As such, the thread will never be released, so there is literally no difference between sync and async in this scenario. Therefore, you're down to just how long it takes to process through the queue of 999 requests (plus your status check at the end). You might have better luck at teasing out a difference if you do something like:
await Task.Delay(500);
Instead of just return Task.FromResult. That way, there's actual idle time on the thread that may allow it to be returned to the pool.
IIS somehow throtling or blocking requests (as mentioned in one of the comments). When I started my WebApi as SelfHosted it started working as expected:
Executing time of isresponsible method after bunch of requests to ASYNC method is very fast, at about 0.02 sec.
Executing time of isresponsible method after bunch of requests to SYNC method is very slow, at about 35 sec.
I'm not sure this will yield any major improvement, but you should call ConfigureAwait(false) on every awaitable in the server, including in GetAsync.
It should produce better use of the threads.

WebApi async actions, do i have to create async methods through all call chain?

I am trying to make my WebApi async in order not to block ASP.net threads handling the requests while accessing the database. So I create the following code. To my understanding when this action is called a new thread away from the ASP.net thread pool is created to handle the GetBalance method and the thread that handled this action request in the past will get freed and returned to the pool until to be used by other requests till the GetBalance method finishes its IO. Is this correct?
Some article I have read suggests that my async calls has to go all the way through all the call chains till it reaches the lowest level async call, in this example an Entity Framework async call. Other wise the new thread created by the code below will still be created in the ASP.net thread pool and I will just be freeing a thread to occupy another, which undermines the whole effort done in the async wait to increase scalability of this WebApi.
Could anybody please explain more on how this works? and if my understanding is correct?
public async Task<Account> Balance(int number)
{
Task<Account> task = GetBalanceAsync(number);
await task;
return task.Result;
}
Task<Account> GetBalanceAsync(int number)
{
return Task.Factory.StartNew(() => GetBalance(number));
}
Account GetBalance(int number)
{
using (AccountServices accountService = new AccountServices())
{
Account account = accountService.Find(number);
return account;
}
}
There's only one thread pool. ASP.NET requests just run on a regular thread pool thread.
To my understanding when this action is called a new thread away from the ASP.net thread pool is created to handle the GetBalance method and the thread that handled this action request in the past will get freed and returned to the pool until to be used by other requests till the GetBalance method finishes its IO. Is this correct?
Yes; your code is taking one thread from the thread pool (StartNew), and then returning a thread to the thread pool (await).
Some article I have read suggests that my async calls has to go all the way through all the call chains till it reaches the lowest level async call, in this example an Entity Framework async call. Other wise the new thread created by the code below will still be created in the ASP.net thread pool and I will just be freeing a thread to occupy another, which undermines the whole effort done in the async wait to increase scalability of this WebApi.
Yes, that's exactly correct. The code posted adds complexity and overhead, and will have worse performance than synchronous code:
public Account Balance(int number)
{
return GetBalance(number);
}
Account GetBalance(int number)
{
using (AccountServices accountService = new AccountServices())
{
return accountService.Find(number);
}
}
A fully-asynchronous solution will have better scalability:
public async Task<Account> Balance(int number)
{
return await GetBalanceAsync(number);
}
Task<Account> GetBalanceAsync(int number)
{
using (AccountServices accountService = new AccountServices())
{
return await accountService.FindAsync(number);
}
}

Changing previous synchronous method to asynchronous

I have a method called from within a program that authorizes card payment which was previously implemented in a synchronous way. However now I want to change it so it runs on a different thread so I can send cancel request once it has started.
It works, but I want to know if this is a good implementation, if there are some things I need to consider like deadlocks etc.
So here is a simplified version of my code:
public void Authorize()
{
lock(object)
{
AuthorizeAsync();
}
}
public async void AuthorizeAsync()
{
// ...
IProgress<string> progressHandler = new Progress<string>(progressString =>
{
UpdateProgressWindow(progressString.ToString());
});
cancellationToken = progressWindow.CancellationTokenSource.Token;
progressWindow.show();
results = await DoAuthorizeAsync(progressHandler, cancellationToken).ConfigureAwait(false);
// ...
}
I mainly want to use async - await because I want the authorization work to run separately from the UI thread so the user can still cancel the operation.
Do you suggest another approach other than async - await?
I am mainly concerned with the fact that I am calling an async method from sync method, I know the best practice is to use async all the way up but I cannot change the rest of the program.
The other concern I have is the lock in Authorize() could it pose any problem? I only want the code to be accessed by one thread at a time.
I am fairly new to this async - await architecture in .net so I'm pretty sure I didn't get it right on my first attempt.

Background work in WCF Rest Service

I have a WCF Rest service that exposes a web method which should start off a long running process and then immediately return an id representing the task that can be used to track the status of the task.
[WebGet]
public Task<Guid> LongRunningProcess()
{
var taskId = new Guid();
var task = Task.Factory.StartNew(() =>
{
//Perform long running task
}
task.ContinueWith(task =>
{
//Send a notification to the client that the task has completed.
}
return taskId;
}
My question is that, is this the correct way to do it? or is there a better and more lightweight approach?
My understanding is that if your work is CPU bound, you are better off executing the work synchronously. With your approach the request will get parked and the original request thread will get freed up, but then are handing off the work to another thread, and the request doesn't complete until that thread is finished. You might as well do the work in the original thread.
If you had some IO in there it would make sense to make that asynchronous as asynchronous IO does not use a thread and it would free up your request thread to handle other requests, which improves your scalability.
UPDATE
I think the approach you are taking is good, but given that you are using .NET 4.5 I'd use async-await as it results in simpler code. I would then use the asynchronous API of IO operations and await its result. Eg:
[WebGet]
public async Task<Guid> LongRunningProcess()
{
var taskId = new Guid();
// IO bound operation
var dbResult = await readFromDbAsync();
// IO bound operation
var dbResult = await readFromDbAsync();
// CPU bound?
generateReport(dbResult);
// IO bound operation
await sendNotification();
return taskId;
}
If you are not familiar with async-await, I have written an intro to it here.
What you sketched up there is (with minor correction) a way to achieve what you want to do. The harder part is the notification of clients (we do so using SignalR hubs successfully, but the exact mechanism is up to you).
The minor correction I spoke about is that the return type of your method should be just Guid in your code above.
Some notes:
Performance-wise the TPL scales pretty well (IMO) but on a lager scale you may want to be able to distribute that long-running tasks over multiple servers etc...
For this case I'll recommend you to have a look at distributes job queues (Resque for example, .NET ports exist) which are perfect for this kind of use cases.

Task.Run() does not runs asynchronously

I have an ASP.NET MVC 3 site that connects to a WCF service. The WCF Service is independent from the site and is hosted in a Windows Service.
Most of the calls are synchronous, so it's not a problem to wait for the WCF to do it's thing.
However, one of those (already implemented) calls takes a bit too long, and, as it essentially does not output anything directly, I wanted to spin it on the service and forget about it.
So I changed my code from:
public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
WcfServiceProxy.DoSlowCalculation(calculationOptions);
ViewBag.Started = true;
return View();
}
to
public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
Task.Run(() =>
{
WcfServiceProxy.DoSlowCalculation(calculationOptions);
});
ViewBag.Started = true;
return View();
}
which, as I understand should start an asynchronous request, and return immediately. Still, the execution is completely synchronous, and the UI is frozen until the operation concludes.
What obvious thing am I missing?
Update:
Also, note that I would prefer not to change the server implementation to an async one, just to de-synchronize the call to the service on the call-site.
Moreover, I've noticed that the StartSlowCalculation method finishes executing, but the server does not return a response until the service method finishes executing.
The WCF Service Proxy just does:
public void DoSlowCalculation(CalculationOptions calculationOptions)
{
//some logging code
Channel.DoSlowCalculation(calculationOptions);
}
so it's completely synchronous, however that shouldn't matter as it should be executed on an independent thread.
A task operation can run in the calling thread, it depends on taskScheduler decision. To help TaskScheduler make a right decision regarding long running call you can specify task creation option TaskCreationOptions.LongRunning.
And you can check whether task operation is running in a separate thread:
int launchedByThreadId = Thread.CurrentThread.ManagedThreadId;
int launchedInThreadId = -1;
Task.Run(() =>
{
launchedInThreadId = Thread.CurrentThread.ManagedThreadId;
WcfServiceProxy.DoSlowCalculation(calculationOptions);
});
// then compare whether thread ids are different
BTW, are you using any kind of Task.Wait() operation? It will block calling thread as well.
EDIT:
You might find following post interesting Is Task.Factory.StartNew() guaranteed to use another thread than the calling thread?
So try out using Task.Factory.StartNew() and specify cancellation token even you do not need it, sounds weird but it seems this guarantees that task will not be run eventually in the calling thread. Correct me If I wrong.
I've done this before.
The most robust way would be to use Asynchronous Controller's, or better yet an independant service such as a WCF service.
But in my experience, i've just needed to do "simple", one-liner task, such as auditing or reporting.
In that example, the easy way - fire off a Task:
public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
//Some Synchronous code.
Task.Factory.StartNew(() =>
{
WcfServiceProxy.DoSlowCalculation(calculationOptions);
});
ViewBag.Started = true;
return View();
}
That's a simple example. You can fire off as many tasks as you want, synchronize them, get notified when they finish, etc.
For more details you can see this links.
https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx

Categories