I have an S1 AppService Plan at Azure with a SQL Database connected. I'm using EF Core.
Every now and then, not only after restarts of the app, database commands are extremely slow. The Profiler says only "waiting". But waiting for what?
Profiler picture
How can I find out what's blocking here?
It can be observed in the shared Profiler snip that your App has been stuck on DbContext.SaveChangesAsync method which is taking time to complete and therefore triggering AWAIT_TIME, but your parallel threads keep executing. Please visit double counting in parallel threads to know more.
The SaveChangesAsync method Asynchronously saves all changes made in this context to the underlying database. In order to cancel this process if it is waiting for the task to complete, you need to use cancellationToken parameter.
Check the sample code below for your reference:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId="cancellationToken")]
public virtual System.Threading.Tasks.Task<int> SaveChangesAsync (System.Threading.CancellationToken cancellationToken);
Helpful link: https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext.savechangesasync?view=entity-framework-6.2.0#System_Data_Entity_DbContext_SaveChangesAsync_System_Threading_CancellationToken_
Related
I have a .NET Core Web API application. The app contains models for db access and a way to send emails to users. My end goal is to call a method nightly (to email users that their registration expired and to mark it expired in the database).
So, in short, I can build an endpoint and call it manually every night. Or build a windows service to call the endpoint. Or build a windows service to do the work. But I want to keep the logic in one application.
My ideal solution would be to have a timer running inside my app and calling a method in a service every 24 hours. Of course, that's not possible, so I am looking at Hangfire. The official documentation seems to indicate that there is a lot of overhead.
Hangfire keeps background jobs and other information that relates to the processing inside a persistent storage. Persistence helps background jobs to survive on application restarts, server reboots, etc.
Do I need this if I just want to call a method?
Background jobs are processed by Hangfire Server. It is implemented as a set of dedicated (not thread pool’s) background threads that fetch jobs from a storage and process them. Server is also responsible to keep the storage clean and remove old data automatically.
Do I even need jobs?
Is there a way to JUST call a method without all this overhead with Hangfire?
tl;dr: Are there options to opt out of the dashboard, database connectivity, etc and just have Hangfire work as a timer?
My ideal solution would be to have a timer running inside my app and calling a method in a service every 24 hours. Of course, that's not possible...
It's very possible, actually, using IHostedService. You should take some time to read the full documentation, but simply, for your scenario, you'd just need something like:
internal class NightlyEmailHostedService : IHostedService, IDisposable
{
private Timer _timer;
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromHours(24));
return Task.CompletedTask;
}
private void DoWork(object state)
{
// send email
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
Then, in Startup.cs just add:
services.AddHostedService<NightlyEmailHostedService>();
Now, that's an extremely naive approach. It basically just kicks off a timer that will run once every 24 hours, but depending on when your app started, it may not always be at night. In reality, you'd likely want to have the timer run every minute or so, and check against a particular time you actually want the email to go out. There's an interesting implementation of handling cron-style times via an IHostedService you might want to reference.
The long and short is that it's very possible to do this all in your app, without requiring anything additional like Hangfire. However, you have to a do a bit more work than you would have to using something like Hangfire, of course.
I have understood the reason of async and await in a WPF application: This permit to the main UI thread not wasting time. The user can interact with UI whereas an I/O operation is waiting at the same time.
What i do not understand is why we see the same concept in ASP.Net Core MVC 2.0.
WebMethods [HttpGet], [HttpPost] should wait anyway before rendering the page...
Thanks
It frees up the cpu to service other requests to your controllers rather than busy wait on whatever async operations you are doing. This answer has a pretty good analogy to help explain:
Think of it like getting on a bus, there's five people waiting to get on, the first gets on, pays and sits down (the driver serviced their request), you get on (the driver is servicing your request) but you can't find your money; as you fumble in your pockets the driver gives up on you and gets the next two people on (servicing their requests), when you find your money the driver starts dealing with you again (completing your request) - the fifth person has to wait until you are done but the third and fourth people got served while you were half way through getting served. This means that the driver is the one and only thread from the pool and the passengers are the requests.
Without an async controller, the passengers behind you would have to wait ages while you looked for your money, meanwhile the bus driver would be doing no work.
I am trying to read thousands of record using c# windows service. I am reading data from RabbitMQ (service broker) topic. My service is able to read thousands of record per sec but issue occurred with processing. I am using Task.Run to process data. Here is the sample code.
Task.Run(() => {
//db transactions
});
Based on my logging, everything works well. Only issue is with concurrent thread, when i check system log, my service has only 255 (concurrent) thread. Where it supposed to be around 1000+.
What could be blocking for my thread?
Is it worthwhile to use Task based Asynch action methods in an ASP.NET MVC project to retrieve a bunch of EntityFramework queries which use LINQ-to-EF. The website is hosted in Azure as is the database. There are quite a few queries that load up a bunch of arrays to send via JSON to an ajax call from the client.
It is worthwhile as long as you are using truly async api (such as EntityFramework async methods) and not creating an async wrappers for example by wrapping your synchronous core in Task.Run or Task.FromResult.
Asynchronous method doesn't suppose to block any thread while it executes (Great article about this).
By the way, because both your application and database are cloud based, it actually makes sense to look into async approach since both your application and you DB can scale.
Technically, it's all three. There's network latency in sending the query/receiving the results. There's CPU-bound work when SQL Server or whatever is actually running the query against your database, and there's I/O as the database itself is a file on the filesystem.
However, from the perspective of your application, interacting with an external database via Entity Framework is network-bound, and is eligible for async as a result.
However, async is not a magical pill that will make your app run faster. If anything using async can actually slow your application down, as there's a lot of overhead to make async work. It's only purpose is to allow the thread doing work to return to the pool while it waits on some task outside of its control to finish. In the case of a database query, the query is sent off to the database which takes some period of time depending on network latency. The database must run the query and construct a result which takes some period of time depending on the resources available on that server. Then, the result is sent back to your application, which again incurs network latency. In a synchronous scenario, your application would just sit there and wait, holding onto the thread. In an async scenario, the thread is released to do other work (server other requests for the web server, etc.) and then when the database response is received the thread is requested back to finish whatever was going on in the application.
In case it's not obvious, the purpose of this is to allow the web server or whatever else you're working with to handle additional load by utilizing periods of what otherwise would be downtime doing other work. In that regard, async is important for using resources efficiently, but it's not necessarily quicker or more performant.
I have an IIS hosted WCF webservice.
It has a method on it (let's call it "ConfirmOrder"). When this method is called, I want to
1. Do some quick stuff to the database, resulting in an OrderId
2. Start a new thread that will do some slow work (e.g. generate an email and send it)
3. Return the OrderId from 1. synchronously to the client.
4. Eventually, when it's finished, the new thread created in 2. will have done all the rest of the processing and sent the email.
Questions:
(1) I did have code like:
// do printing and other tasks
OrderConfirmedThreadHelper helper = new OrderConfirmedThreadHelper(userSession, result);
// some things first (like generating barcodes) in this thread
Logger.Write(basket.SessionId, String.Format("Before ConfirmOrderSync"), LogCategoryEnum.Sales, System.Diagnostics.TraceEventType.Verbose);
helper.ConfirmOrderSync();
Logger.Write(basket.SessionId, String.Format("After ConfirmOrderSync"), LogCategoryEnum.Sales, System.Diagnostics.TraceEventType.Verbose);
// slower things (like rendering, sending email) in a separate thread
Thread helperThread = new Thread(new ThreadStart(helper.ConfirmOrderAsync));
helperThread.Start();
return result;
but it seemed to cause problems; at least, the service kept locking up. Is this a bad thing to do?
(2) I tried changing it to
// slower things (like rendering, sending email) in a separate thread
ThreadPool.QueueUserWorkItem(new WaitCallback(helper.ConfirmOrderAsync));
but the ThreadPool thread seems to be being killed as soon as the main thread has finished, because it's a Background thread.
Is there a better way of doing this - short of writing a whole new windows service to communicate with?
If the second thead finishes after the request thread (the one that comes from the browser) you're in problems, since it'll get reclaimed by the runtime and terminated.
If you can afford to wait (if it's only going to send an email i'll be a couple of seconds) you can use ManualResetEvent to synchronize one thread to wait for the other to finish and clean up gracefully.
If you can't wait, well the best choice in this case for the mail process is one of the following
A Windows Service.
An .ashx you can call from your client code with a jquery ajax call passing the necessary data to send the mail.
A batch job (a scheduled task, a sql server job, etc) that reads pending mails to be sent from the DB and sends them. It would run every X minutes, so you wouldn't have to worry
Hope that helps!