I'm using an asp.net 4.5 web application and asp.net membership. I implement the MembershipProvider interface which has a method:
public override bool ValidateUser(string username, string password)
The code within this method for my implementation has to make two WCF service calls which can be expensive. In the spirit and my desire of learning and using async, I'd like to make the code use async await.
I created my two Tasks that need to call the WCF service methods. What I'm unclear on is how to properly use async from the "ValidateUser" method to call these Tasks. I cannot change this method signature to add async as I would have to then change bool to Task so I'm stuck with a method signature that cannot be adored with the async modifier.
In this case how can I call my two tasks and have them run on a background thread? I know I can use Task.Result but my understanding is that would be a synchronous call and is frowned upon. I'm not sure of the gain by using Task.Result as my intention is to background thread my two WCF service method calls.
Well, you can certainly call the tasks asynchronously inside your membership provider, you just can't call ValidateUser asynchronously.
The old Membership API was created long before Async existed and is not compatible. You could wrap this around an async method. Here's a blog entry about it.
http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx
The gist is something like this (change to use for ValidateUser)
public Task SleepAsync(int millisecondsTimeout)
{
return Task.Run(() => Sleep(millisecondsTimeout));
}
Related
I am trying to write async code in asp.net 4.8 but and the problem is that HttpContext is null after returning from await. This means that the async code works correctly which is good, but the HttpContext is needed by the original code.
From the comments in below answer by Darin Dimitrov it shows that HttpContext is having this issue since 4.6.1.
Why is HttpContext.Current null after await?
var domains = HttpContext.Current.Cache.Get("domains") as Dictionary<String, Domains>;
if (domains == null)
{
var x = await TrackingMethods.GetTableForCacheAsync().ConfigureAwait(false);
domains = x.domains;
}
/// HttpContext.Current is null here
ConfigureAwait(false) means "don't resume on the captured context". By specifying ConfigureAwait(false), your code is telling the runtime that it doesn't need the ASP.NET request context. But your code does need the ASP.NET request context, since it depends on HttpContext.Current. So using ConfigureAwait(false) here is wrong.
If I don't use ConfigureAwait(false) the code will not run.
This is likely because your code is blocking further up the call stack, causing a deadlock. The ideal solution is to remove the blocking - i.e., use async all the way. Using async all the way is preferable to blocking with ConfigureAwait(false).
However, there are a handful of scenarios where this isn't possible. For example, ASP.NET 4.8 doesn't have proper asynchronous support for MVC action filters or child actions. If you're doing something like this, then you have a couple of options:
Make it synchronous all the way instead of async all the way.
Keep the blocking-over-async-with-ConfigureAwait(false) antipattern but copy out everything your code needs from HttpContext.Current first and pass that data as explicit parameters so the code no longer has a dependency on the ASP.NET request context.
I have a CRUD app in Blazor that simply fetches the assignment lists from a table and has an AssignmentReminderService for data access layer that has a method (async version)
public async Task<AssignmentReminder> AddAssignment(AssignmentReminder assignment)
{
_context.assignments.Add(assignment);
await _context.SaveChangesAsync();
return assignment;
}
I can also call the method with synchromus code as :
public AssignmentReminder AddAssignment(AssignmentReminder assignment)
{
_context.assignments.Add(assignment);
_context.SaveChanges();
return assignment;
}
Now it is just one database being accessed from a local server(could be hosted on cloud as well) with just one assignment table and the default authentication/authorization tables generated when one uses Individual User Account (aspnetusers, aspnetroles etc)
Can someone let me know which of the two ways I should use (between async or sync) method declaration?
In the general case, you should use asynchronous APIs if they are available. This will result in greater scalability on the server side, since asynchrony will allow the calling request thread to be used for other requests while the asynchronous operation is in progress.
There are specific scenarios where this guideline doesn't apply. E.g., if you're calling a generic asynchronous API (like Stream.ReadAsync) but you know that the implementation is actually synchronous (like MemoryStream). But in general, if there's an asynchronous API, then that's the one you should use.
You should be clear about the version of blazor you're talking about, because using async methods in the client is different from using them in the server version.
which of the two ways I should use (between async or sync) method declaration?
The first one.
The scarce resource here are the Threads. You want to keep their number down, and the first approach enables that by releasing the Thread to do other work.
In the second approach the Thread is suspended for the duration of the I/O operation. You would need more Threads to handle the same number of requests.
So using async I/O lets the same hardware handle more requests at the same time.
I recently started using Hangfire to handle my background jobs in an ASP.NET project.
My jobs are involving lots, lots (and lots) of HTTP calls using WebRequest (I may migrate to something else, but that's for later).
While browsing SO on this subject, I stumbled upon people who do async calls in hangfire.
Is there any point in using async/await tasks inside a Hangfire job ? I'm aware that it is a queue, so jobs won't execute concurrently, but since my project has no GUI, is there any reason I would use async/await to do my HTTP calls inside a Hangfire job ?
PS : The requests that are involving a long-running job use the Task "design pattern", so clients won't experience any timeout
You can absolutely use Hangfire to run async methods, and use awaits within those async methods.
The SO question you linked to was making a blocking Wait call on the method passed to Hangfire to be serialized and then later executed by the hangfire service.
This is very different from something like
hangfireClient.Enqueue(() => myClass.RunAsync());
where RunAsync is an async method that contains awaits.
public async Task<bool> RunAsync() {
//do your work
var subJob = new worker();
return await subJob.DoWork();
}
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.
I consume Java Service in my .NET appliaction. I have one question: When service serialize in .NET he also create Async methods. For example for GetPersons() method service create GetPersonsAsync() which is return void. In which cases I can use this Async methods and what the destination of these methods.
Generally, for async methods, you also need to specify a callback method. The called web method immediately returns but keeps working in the backround. When its done, it invokes your callback method with its results