I am adding documentdb to an existing application (~500kloc). There is no way I can do an 'async all the way' rewrite of this app even if I wanted to.
All the C# APIs are async . The obvious way to sync with these calls is to .Wait() them. This is what several MS sample apps do, however when I previously asked a similar question the consensus was 'do not do .wait you risk deadlocks'
I found this exact question in SO that had no answer, just comments. One said 'do .wait', one said 'use await' on said 'you cant do it'
'use await' doesnt resolve the question since we are still async, then none of these comments provide an answer
All DocumentDB async API will use Task.Run to run the task when there is a synchronization context (ASP/WPF/Winforms).
That means, it is safe to call .Result or .Wait directly on DocumentDB C# API.
You could call your async method from a non-async method using:
var myThread = System.Threading.Tasks.Task.Run(async () => await
DoSomethingAsync());
And then you can avoid deadlock by calling
myThread.Wait();
Blocking calls (n samples are due to lack of 'async main' before C#7.
Its recommended to not use blocking calls in you application as much as possible.
Just calling YourMethodAsync().GetAwaiter().GetResult() to run it synchronously and avoid deadlock
Related
I found some ways to call an async method on a sync method, but I don't know what is the best way in .net core and why?
DebugLog.Log(ex.ToString()).GetAwaiter();
System.Threading.Tasks.Task.Run(async () => await DebugLog.Log(ex.ToString()));
DebugLog.Log(ex.ToString()).RunSynchronously();
DebugLog.Log(ex.ToString()).ConfigureAwait(default);
I don't know what is the best way in .net core and why?
There is no best way. If there was, then everyone would just use that.
There are a variety of approaches, each with their own drawbacks. The two most common are:
GetAwaiter().GetResult() (i.e., direct blocking) - can deadlock.
Task.Run(...).GetAwaiter().GetResult() (i.e., block a thread pool thread) - doesn't work if the ... requires the current context.
RunSynchronously should never be used.
I have seen some answers to this question using a Java implementation; however, I wasn't able to convert it successfully. The Java implementation seems to use a try, catch approach to determine whether the FirebaseAuthUserCollisionException is ran into or not. But from researching online, it seems try, catch is obsolete in Kotlin.
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email,password)
.addOnCompleteListener(){it:Task<AuthResult>
if(!it.isSuccessful)
This is the only piece of code I have so far. I appreciate all help! Thank you in advance.
try/catch is not obsolete in Kotlin. It still works essentially the same way. It's just not very useful when working with the asynchronous APIs provided by Firebase and Play services.
The Firebase APIs are all asynchronous, so you need to check for errors in the callbacks that you attach to the Task object returned from the call. This is the same for both Java and Kotlin. You might want to learn more about the Task API in order to better deal with Firebase APIs that return a Task to represent asynchronous work. In the code you've shown, you check for errors in an onComplete listener by looking at the exception object in the result if it wasn't successful:
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email,password)
.addOnCompleteListener() { it:Task<AuthResult>
if (!it.isSuccessful) {
val exception = it.exception
// do something with this exception, according to the Firestore API docs
}
I am migrating my current project to core, and in my current project I have many synchronous method calls from UserManagerExtension class like Create, FindById, AddToRole etc. But despite thorough searching online I am not able to find the same in core.
Is it deprecated in core 2.0? If not, what is the namespace and how to include it?
As far as I can tell, they are gone. However, their existence was suspect even before. All the extensions did was simply run the async versions "synchronously", which basically means they spun off a task that blocked on the async call until it completed. While this technically satisfies having a "synchronous" method, it's actually really bad for web applications as you're sacrificing threads from your pool to do the work synchronously.
In ASP.NET MVC, it was a necessary evil, though, since there were many aspects that did not support async: child actions, action filters, etc. However, in Core, everything is async, and things happening in a web application space should be async. Therefore, there's simply no good reason to ever use sync methods, so that's probably why they no longer exist.
If you still need to run the async methods as sync, for some reason, you can simply block on them yourself:
var user = UserManager.FindByIdAsync(id).GetAwaiter().GetResult();
Be aware, though, that can deadlock in certain situations, because of the context shift. The two ways to avoid that are:
Use ConfigureAwait(false)
var user = UserManager.FindByIdAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
However, you cannot use ConfigureAwait(false) in something like an action method, since the context must be maintained in order to complete the response. You can use it in a method called by the action method, though:
private ApplicationUser GetUser(string id)
{
return UserManager.FindByIdAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
...
var user = GetUser(id);
Run it in a different thread
Task.Run(() => {
var user = UserManager.FindByIdAsync(id).GetAwaiter().GetResult();
// code here that needs `user`
});
As you can see, with this method the work you send off must be self-contained, so it's probably not a good fit in most scenarios. Also, again, this is extremely bad for web applications.
Long and short, there's not really a good way to run async as sync, and you should avoid it as much as possible. Async should be async all the way. That did use to be an issue in MVC, but now it's not with Core.
Correction: as follows from two answers, the problem looks to be specific to dart as C# implements Task.Wait allowing to achieve the desired effect. I would be grateful for any further information on the reasons why this is not possible in dart or how to achieve it there. I would be happy to close the question in its current form.
There are situations where it could make sense to have synchronous functions use asynchronous calls internally waiting for their completion before delivering the result. This is explicitly not allowed in both C# and Dart: anything that uses await must be marked as async (thus returning a future).
A simple example in Dart, but the same is valid for C#:
Disclaimer: this is not how I would do things, so do not suggest a "correct" solution of converting all methods to async; the code here is just to illustrate the question.
I have a fully asynchronous implementation of a generic wrapper for HTTP requests to some particular REST API. It does some login, authentication etc.:
class RequestProcessor {
Future post(String path, [payload]) async {
return request("POST", path, payload);
}
}
I would like to implement a high-level user-facing API translating to requests to the REST-API. Some of those methods I'd like to have synchronous. This is what I would like and am not allowed to have:
class API {
final RequestProcessor processor;
API(this.processor);
// this takes long and should be asynchronous, happy with a future (OK)
Future getQueryResults(query) async {
return await processor.post("/query", query);
}
// here I would prefer to have it synchronous (COMPILE ERROR)
String getVersion() {
return await processor.post("/version");
}
}
Question: Why is this not allowed?
It's a design choice.
Dart is single-threaded - each synchronous function call will run to completion before allowing any other code to run. If you allow a synchronous function to block until a future is complete, then no other code will run and the future will never complete (because the code that would complete it can't run).
It is possible to have a system that allows other code to run while one synchronous function is blocked. That requires either having more than one active stack (parallel or not), or implicitly transforming the entire program to be async. Neither choice is great when you compile to JavaScript, so Dart did not try to do that.
The await is an asynchronous wait so it does not make sense to have it in a synchronous function. To be asynchronous the method needs to return when the awaited operation is initiated, whereas the synchronous method needs to run to completion.
You can use a synchronous wait instead, in which case your method does not need to be async. In C# you can do this by calling the Wait() method on the returned task.
Because waiting and returning a future is fundamentally different.
Returning a future frees the current thread and optionally schedules a continuation for later, waiting blocks the current thread.
For example, in a UI thread, returning a future is fine but waiting will cause the UI to hang, in a web server thread waiting will block the thread and prevent the web server from handling more request, etc.
It's even possible waiting for what should be an async operation will cause a deadlock.
.net provide Task.Wait for when you know waiting is fine, I don't know about dart - but this is not automatic (except for await inside catch clauses in async methods in C#)
In Dart marking a function/method async tells the VM that it needs to rewrite the code before executing it.
await doesn't change an async function to a sync one, the function is still async, it just allows nicer syntax than then(() { return ...then(() { return...})}) chains.
If you make an async call everything following is async, there is nothing you can do about it.
I am using ASP.NET 4.5, with <httpRuntime targetFramework="4.5" /> set.
I have an old data helper library method that returns a SQLDatatable using SQLDataAdapter.Fill().
I want to add a method to return Task(of SQLDatatable) - an async equivalent of the old method.
The code I have is like below (only the portion of code that matters is included):
Note:
GetConnectionString() returns the sql connection string
GetSqlCmd(...) returns a SQLCommand object
LogError() logs any exception
Using conn As New SqlConnection(GetConnectionString())
Try
cmd = GetSqlCmd(strSQL, conn, hash)
Await conn.OpenAsync().ConfigureAwait(False)
Using datareader = Await cmd.ExecuteReaderAsync().ConfigureAwait(False)
userDataTable.Load(datareader)
End Using
Catch ex As Exception
LogError(ex)
End Try
End Using
And the code works in the ASP.NET application, once I add await to the library method call.
The thing I'm not really sure is if the code above makes sense. Certainly the SQLDataReader is async, but SQLDataTable.Load(datareader) doesn't appear to use ReadAsync (as far as I can tell)...
Does this fact make the above code pointless - meaning, "ExecuteReaderAsync without ReadAsync" is pointless?
It is not pointless. Using async is not all or nothing. In a web app async IO is about block threads less. It is not required to not block them at all.
You have eliminated the blocking resulting from OpenAsync and ExecuteReaderAsync. Draining the reader is still synchronous.
That said, most web apps don't get any benefit at all from using async. For example it does not magically make your queries faster or add more capacity to the database server. So chose wisely.
It is not "pointless", rather it helps that specific piece of code scale better. You don't have to use it everywhere but if you need to improve scalability, you should as much as possible.
Async is not about making anything faster, it is about making an app scalable. It is misleading at best (and totally wrong at worst) for this answer to say "...most web apps don't get any benefit at all from using async. For example it does not magically make your queries faster or add more capacity to the database server".
The apps that will get the most from going async are those that require scalability. Here is another answer on SO that has more detail - Not much difference between ASP.NET Core sync and async controller actions
Not using async means your calls are blocking waiting for the db to do something. Using async means those threads that would've been blocking can actually do something else. This increases scalability. Microsoft's own Bing.com is internally run on SqlServer so SqlServer has no problem with scalability when designed and implemented correctly.