Convert async to sync for HttpClient.SendAsync - asynchronous

I want to use a REST-call like this:
private async Task<HttpResponseMessage> SendRequestHelperAsync(HttpRequestMessage message, CancellationToken ct)
{
var response = await HttpClient.SendAsync(message, ct).ConfigureAwait(false);
return response;
}
from a non-async method. When I use it like this:
var response = SendRequestHelperAsync(message, ct).Result;
it gets stuck. When I use it directly, it gets stuck as well:
HttpResponseMessage response = HttpClient.SendAsync(message, ct).Result;
When I was looking for some solution, I came across using a task like this:
var task = Task.Run(async () => { await SendRequestHelperAsync(message, ct); });
but then how do I get the result back?
(I am using it from .Net Framework 4.8, WinForms Application.)

I want to use [async code] from a non-async method.
The best answer is "don't". Instead, go async all the way.
You could use Task.Run as a workaround; this is the thread pool hack, which will work in this specific case (warning: it does not work in every case, specifically, if the code in the Task.Run delegate accesses UI elements, then this hack will not work). The thread pool hack supports return types, as such:
var response = Task.Run(async () => await SendRequestHelperAsync(message, ct))
.GetAwaiter().GetResult();
However, the best answer is still "don't". The fact that you're deadlocking (as explained in detail on my blog) implies that this code is being run on the UI thread, and the solution is attempting to block the UI thread on a network request. Blocking the UI thread is a poor user experience.
Instead, the best solution is to redesign the UI so that no blocking is necessary. This is usually done by adding some kind of spinner or "loading..." UI element, and then updating the UI when the asynchronous operation completes.

Related

In ASP.NET, why does DbSet.LastAsync() not exist?

I've make some codes implementing some web API.
This API method returns last record of Foo Table.
public class FooController : ApiController
{
private FooContext db = new FooContext();
// GET: api/Foo
[ResponseType(typeof(Foo))]
public async Task<IHttpActionResult> GetLastFoo()
{
Foo foo = await db.Foo.Last();
if (foo == null)
{
return NotFound();
}
return Ok(foo);
}
}
I want make this API asynchronous, but there is no LastAsync() method.
Why and how can I solve it?
Thanks in advance.
You should not use Task.Run in ASP.NET:
Async and await on ASP.NET are all about I/O. They really excel at
reading and writing files, database records, and REST APIs. However,
they’re not good for CPU-bound tasks. You can kick off some background
work by awaiting Task.Run, but there’s no point in doing so. In fact,
that will actually hurt your scalability by interfering with the
ASP.NET thread pool heuristics. If you have CPU-bound work to do on
ASP.NET, your best bet is to just execute it directly on the request
thread. As a general rule, don’t queue work to the thread pool on
ASP.NET.
From Async Programming : Introduction to Async/Await on ASP.NET
Still it does not mean you can't use async and await in ASP.NET for I/O (and that's what you want) just use real async methods and not a fake async wrappers over synchronous methods (that will just push the work into other ThreadPool thread and you will not gain any performance benfit from it).
Since you don't have LastAsync method in EF I suggest you to use OrderBy to order your collection as you want and to use FirstAsync method (or FirstAsync overload that supports lambda predicate) instead of using Last method, FirstAsync is a true async I/O method that is supported in EF.
More info about when it's appropriate to use Task.Run can be found in Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation article in Stephen Cleary's blog.
Your question why there is no LastAsync method in the first place should be directed to the team at Microsoft that desiged EF api, but my guess is that they didn't bother implementing it since it is so easy to achieve the same functionally with FirstAsync method as I suggested.
A working version of that code would look like this:
public class FooController : ApiController
{
private FooContext db = new FooContext();
// GET: api/Foo
[ResponseType(typeof(Foo))]
public async Task<IHttpActionResult> GetLastFoo()
{
Foo foo = await db.Foo.OrderByDesc(x=> x.Timestamp).FirstOrDefaultAsync();
if (foo == null)
{
return NotFound();
}
return Ok(foo);
}
}
Last etc don't work against an EF IQueryable because SQL doesn't have an equivalent command
about how to solve it
you can use
await Task.Run(()=>db.Foo.Last());

How to rewrite synchronous controller to be asynchronous in Play?

I'm using Play framework 2.2 for one of my upcoming web application. I have implemented my controllers in synchronous pattern, with several blocking calls (mainly, database).
For example,
Synchronous version:
public static Result index(){
User user = db.getUser(email); // blocking
User anotherUser = db.getUser(emailTwo); // blocking
...
user.sendEmail(); // call to a webservice, blocking.
return ok();
}
So, while optimising the code, decided to make use of Asynchronous programming support of Play. Gone through the documentation, but the idea is still vague to me, as I'm confused about how to properly convert the above synchronous block of code to Async.
So, I came up with below code:
Asynchronous version:
public static Promise<Result> index(){
return Promise.promise(
new Function0<Result>(){
public Result apply(){
User user = db.getUser(email); // blocking
User anotherUser = db.getUser(emailTwo); // blocking
...
user.sendEmail(); // call to a webservice, blocking.
return ok();
}
}
);
}
So, I just wrapped the entire control logic inside a promise block.
Is my approach correct?
Should I convert each and every blocking request inside the controller, as Asynchronous, or wrapping several blocking calls inside single Async block is enough?
The play framework is asynchronous by nature and it allows the creation of fully non-blocking code. But in order to be non-blocking - with all its benefits - you can't just wrap your blocking code and expect magic to happen...
In an ideal scenario, your complete application is written in a non-blocking manner. If this is not possible (for whatever reason), you might want to abstract your blocking code in Akka actors or behind async interfaces which return scala.concurrent.Future's. This way you can execute your blocking code (simultaneously) in a dedicated Execution Context, without impacting other actions. After all, having all your actions share the same ExecutionContext means they share the same Thread pool. So an Action that blocks Threads might drastically impact other Actions doing pure CPU while having CPU not fully utilized!
In your case, you probably want to start at the lowest level. It looks like the database calls are blocking so start by refactoring these first. You either need to find an asynchronous driver for whatever database you are using or if there is only a blocking driver available, you should wrap them in a future to execute using a DB-specific execution context (with a ThreadPool that's the same size as the DB ConnectionPool).
Another advantage of abstracting the DB calls behind an async interface is that, if at some point in the future, you switch to a non-blocking driver, you can just change the implementation of your interface without having to change your controllers!
In your re-active controller, you can then handle these futures and work with them (when they complete). You can find more about working with Futures here
Here's a simplified example of your controller method doing non-blocking calls, and then combining the results in your view, while sending an email asynchronous:
public static Promise<Result> index(){
scala.concurrent.Future<User> user = db.getUser(email); // non-blocking
scala.concurrent.Future<User> anotherUser = db.getUser(emailTwo); // non-blocking
List<scala.concurrent.Future<User>> listOfUserFutures = new ArrayList<>();
listOfUserFutures.add(user);
listOfUserFutures.add(anotherUser);
final ExecutionContext dbExecutionContext = Akka.system().dispatchers().lookup("dbExecutionContext");
scala.concurrent.Future<Iterable<User>> futureListOfUsers = akka.dispatch.Futures.sequence(listOfUserFutures, dbExecutionContext);
final ExecutionContext mailExecutionContext = Akka.system().dispatchers().lookup("mailExecutionContext");
user.andThen(new OnComplete<User>() {
public void onComplete(Throwable failure, User user) {
user.sendEmail(); // call to a webservice, non-blocking.
}
}, mailExecutionContext);
return Promise.wrap(futureListOfUsers.flatMap(new Mapper<Iterable<User>, Future<Result>>() {
public Future<Result> apply(final Iterable<User> users) {
return Futures.future(new Callable<Result>() {
public Result call() {
return ok(...);
}
}, Akka.system().dispatcher());
}
}, ec));
}
It you don't have anything to not block on then there may not be a reason to make your controller async. Here is a good blog about this from one of the creators of Play: http://sadache.tumblr.com/post/42351000773/async-reactive-nonblocking-threads-futures-executioncont

Chain the completion of an async function to another

I am working on a Windows Store (C++) app. This is a method that reads from the database using the web service.
task<std::wstring> Ternet::GetFromDB(cancellation_token cancellationToken)
{
uriString = ref new String(L"http://myHost:1234/RestServiceImpl.svc/attempt");
auto uri = ref new Windows::Foundation::Uri(Helpers::Trim(uriString));
cancellationTokenSource = cancellation_token_source();
return httpRequest.GetAsync(uri, cancellationTokenSource.get_token()).then([this](task<std::wstring> response)->std::wstring
{
try
{
Windows::UI::Popups::MessageDialog wMsg(ref new String(response.get().c_str()), "success");
wMsg.ShowAsync();
return response.get();
}
catch (const task_canceled&)
{
Windows::UI::Popups::MessageDialog wMsg("Couldn't load content. Check internet connectivity.", "Error");
wMsg.ShowAsync();
std::wstring abc;
return abc;
}
catch (Exception^ ex)
{
Windows::UI::Popups::MessageDialog wMsg("Couldn't load content. Check internet connectivity.", "Error");
wMsg.ShowAsync();
std::wstring abc;
return abc;
}
} , task_continuation_context::use_current());
}
I'm confused how to return the received data to the calling function. Now, I am calling this function in the constructor of my data class like this:
ternet.GetFromDB(cancellationTokenSource.get_token()).then([this](task<std::wstring> response)
{
data = ref new String(response.get().c_str());
});
I am getting a COM exception whenever I try to receive the returned data from GetFromDB(). But this one runs fine:
ternet.GetFromDB(cancellationTokenSource.get_token());
Please suggest a better way of chaining the completion of GetFromDB to other code. And how to get the returned value from inside the try{} block of GetFromDB() 's then. Please keep in mind I am a very new student of async programming.
If the continuation of the call to GetFromDB is happening on the UI thread (which I believe it will by default, assuming the call site you pasted is occurring in the UI thread), then calling get() on the returned task will throw an exception. It won't let you block the UI thread waiting for a task to finish.
Two suggestions, either of which should fix that problem. The first should work regardless, while the second is only a good option if you're not trying to get the response string to the UI thread (to be displayed, for example).
1) Write your continuations (lambdas that you pass to then) so that they take the actual result of the previous task, rather than the previous task itself. In other words, instead of writing this:
ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... });
write this:
ternet.GetFromDB(...).then([this](std::wstring response) { ... });
The difference with the latter is that the continuation machinery will call get() for you (on a background thread) and then give the result to your continuation function, which is a lot easier all around. You only need to have your continuation take the actual task as an argument if you want to catch exceptions that might have been thrown by the task as it executed.
2) Tell it to run your continuation on a background/arbitrary thread:
ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... }, task_continuation_context::use_arbitrary());
It won't care if you block a background thread, it only cares if you call get() on the UI thread.

Task.ContinueWith confusion

With ASP.NET 4.5 I'm trying to play with the new async/await toys. I have a IDataReader-implementing class that wraps a vendor-specific reader (like SqlDatareader). I have a simple ExecuteSql() method that operates synchronously like so:
public IDataReader ReaderForSql(string sql)
{
var cmd = NewCommand(sql, CommandType.Text);
return DBReader.ReaderFactory(cmd.ExecuteReader());
}
What I want is an Async version of this. Here's my first try:
public Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
var cmd = NewCommand(sql, CommandType.Text);
return cmd.ExecuteReaderAsync(ct)
.ContinueWith(t => DBReader.ReaderFactory(t.Result));
}
and I use it:
using (var r = await connection.ReaderForSqlAsync("SELECT ...", cancellationToken))
{
...
}
This works great in my limited testing so far. But after watching this Cloud9 video a few times: http://channel9.msdn.com/Events/aspConf/aspConf/Async-in-ASP-NET I got worreid about warnings they gave regarding:
ContinueWith consuming extra threadpool resources - Readerfactory is very light!
Task.Result blocking
and since I am passing a ContinuationToken to ExecuteReaderAsync() it seems cancellation is just yet another reason ExecuteReaderAsync() could fail (it's SQL after all!)
What will be the state of the task when I try to ContinueWith it? Will t.Result block? throw? do the wrong thing?
ContinueWith will use the current task scheduler (a thread pool thread) by default, but you can change that by passing TaskContinuationOptions.ExecuteSynchronously and an explicit TaskScheduler.
That said, I would make this as a first effort:
public async Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
var cmd = NewCommand(sql, CommandType.Text);
var readerResult = await cmd.ExecuteReaderAsync(ct).ConfigureAwait(false);
return DBReader.ReaderFactory(readerResult);
}
async and await handle all the ContinueWith delicacies and edge conditions in a consistent manner for you. It may be possible to complicate this code to be faster if performance testing indicates it's a serious problem.
Result blocks if the task has not completed. But in the continuation handler it already has. So it does not block. You are doing the right thing.
When you invoke Result on a faulted task (and you say this might happen) the exception is rethrown. This causes your continuation to fault with the same exception which causes the final task returned from ReaderForSqlAsync to also be faulted. This is a good thing: The entire chain of tasks faulted and all exceptions have been observed (on contrast to being swallowed). So this is best-practice, too.
Using a thread for compute-bound work is always ok. So again, you are doing the right thing using ContinueWith. You have to compute the IDataReader somewhere after all. You cannot not compute it.

Suggestions for simple ways to do Asynchronous processing in Grails

Let's say I have a simple controller like this:
class FooController {
def index = {
someVeryLongCompution() //e.g crawl a set of web pages
render "Long computation was launched."
}
}
When the index action is invoked, I want the method to return immediately to the user while running the long computation asynchronously.
I understand the most robust way to do this would be to use a message broker in the architecture, but I was wondering if there is a simpler way to do it.
I tried the Executor plugin but that blocks the http request from returning until the long computation is done.
I tried the Quartz plugin, but that seems to be good for periodic tasks (unless there is a way to run a job just once?)
How are you guys handling such requests in Grails?
Where do you want to process veryLongComputation(), on the same Grails server, or a different server?
If the same server, you don't need JMS, another option is to just create a new thread and process the computation asynchronously.
def index = {
def asyncProcess = new Thread({
someVeryLongComputation()
} as Runnable )
asyncProcess.start()
render "Long computation was launched."
}
If you use a simple trigger in Grails Quartz and set the repeatCount to 0, the job will only run once. It runs separate from user requests, however, so you'd need to figure out some way to communicate to user when it completed.
I know this is a very old question, just wanted to give an updated answer.
Since grails 2.3, the framework supports async calls using Servlet 3.0 async request handling (of course, a servlet 3.0 container must be used and the servlet version should be 3.0 in the configuration, which it is per default)
It is documented here : http://grails.org/doc/latest/guide/async.html
In general, there are two ways achieving what you asked for:
import static grails.async.Promises.*
def index() {
tasks books: Book.async.list(),
totalBooks: Book.async.count(),
otherValue: {
// do hard work
}
}
or the Servlet Async way:
def index() {
def ctx = startAsync()
ctx.start {
new Book(title:"The Stand").save()
render template:"books", model:[books:Book.list()]
ctx.complete()
}
}
Small note - The grails method is using promises, which is a major (async) leap forward. Any Promise can be chained to further promised, have a callback on success and fail etc'
Have you tried Grails Promisses API? It should be as simple as
import static grails.async.Promise
import static grails.async.Promises
class FooController {
def index = {
Promise p = Promises.task {
someVeryLongCompution() //e.g crawl a set of web pages
}
render "Long computation was launched."
}
}
Try Spring events plugin - It supports asynchronous event listeners.
If you'd like to use the Quartz plugin (as we always do), you can do it like this. It works well for us:
DEFINE A JOB (with no timed triggers)
static triggers = {
simple name:'simpleTrigger', startDelay:0, repeatInterval: 0, repeatCount: 0
}
CALL <job>.triggerNow() to manually execute the job in asynchronous mode.
MyJob.triggerNow([key1:value1, key2: value2]);
Pro Tip #1
To get the named parameters out the other side...
def execute(context) {
def value1 = context.mergedJobDataMap.get('key1');
def value2 = context.mergedJobDataMap.get('key2');
...
if (value1 && value2) {
// This was called by triggerNow(). We know this because we received the parameters.
} else {
// This was called when the application started up. There are no parameters.
}
}
Pro Tip #2
The execute method always gets called just as the application starts up, but the named parameters come through as null.
Documentation: http://grails.org/version/Quartz%20plugin/24#Dynamic%20Jobs%20Scheduling
The best solution for this kind of problem is to use JMS, via the JMS plugin.
For a simpler implementation, that doesn't requires an externel server/service, you can try the Spring Events plugin.
Grails 2.2.1 Solution I had an additional requirement that said the report had to auto pop a window when it was complete. So I chose the servlet way from above with a twist. I replaced the render a view with a json formatted string return it looked like this.
Additionally my client side is not a gsp view, it is ExtJS 4.1.1 (a HTML5 product)
enter code here
def index() {
def ctx = startAsync()
ctx.start ({
Map retVar = [reportId: reportId, success: success];
String jsonString = retVar as JSON;
log.info("generateTwoDateParamReport before the render out String is: " + jsonString);
ctx.getOriginalWebRequest().getCurrentResponse().setContentType("text/html");
ctx.getOriginalWebRequest().getCurrentResponse().setCharacterEncoding("UTF-8");
log.info("current contentType is: "ctx.getOriginalWebRequest().getCurrentResponse().contentType);
try {
ctx.getOriginalWebRequest().getCurrentResponse().getWriter().write(jsonString);
ctx.getOriginalWebRequest().getCurrentResponse().getWriter().flush();
ctx.getOriginalWebRequest().getCurrentResponse().setStatus(HttpServletResponse.SC_OK);
}
catch (IOException ioe)
{
log.error("generateTwoDateParamReport flush data to client failed.");
}
ctx.complete();
log.info("generateNoUserParamsReport after complete");
});
}

Resources