Updating data base asynchronously using EF6, Inside Task.Run? Performance issue - c#

I have a WCF server application that should accept a call from the client, update in db and return a response to the client. The response to the client is independent in the result of the db update, an exception in the update has no effect on the response. I am using EF6 async methods. I can use Task.Run and inside call the async method:
public Boolean Init(){
//do something
Task.Run(async () => await UpdateDBAsync().ConfigureAwait(false))
.ContinueWith(res => _logger.Warn("cannot insert session to DB"),
TaskContinuationOptions.OnlyOnFaulted);
//do some more
return true;
}
The above will assure that the response to the client will be immediate and will not be dependent in the DB response time.
The second approach is not using the Task.Run:
public Boolean Init(){
//do something
UpdateDBAsync().ContinueWith(res => _logger.Warn("cannot insert session to DB"),
TaskContinuationOptions.OnlyOnFaulted);
//do some more
return true;
}
The first approach will allocate a thread pool thread while the second would run on the current thread. My main goal is that the response to the client will be fast as possible and my question is will the first approach (Using the Task.Run) will be faster or will the creation of the thread pool thread decrease the overall performance of the application making the response slower.
Note: in the second approach I am using ContinueWith() and not await because I want to do more things and return a response
EDIT
The UpdateDBAsync method:
public async Task UpdateDBAsync()
{
using (var context = SqlConnectionProvider.GetSqlDbEntityContext())
{
try
{
await _retryPolicy.ExecuteAsync(() => context.SaveChangesAsync());
}
catch (DbUpdateException ex)
{
}
}
}

Both are functionally identical, one just needs to take the extra time to be scheduled by a thread pool thread before it can do its work, so yes, it will obviously be slower. It may not be a huge amount slower, but it'll be slower.
The only real possible exception is if UpdateDBAsync is not actually asynchronous, and in fact does a bunch of work synchronously despite its name. As long as the name is not a lie, there's no reason to use Task.Run here.

Related

can I update one entity in parallel threads c#

using: Asp.net Core, Entityframework Core, ABP 4.5
I have a user registration and initialization flow. But it takes a long time. I want to parallelize this. This is due to updating from the same entity, but with a different field.
My goal:
1. The endpoint should respond as soon as possible;
2. Long initialization is processed in the background;
Code-before (minor details omitted for brevity)
public async Task<ResponceDto> Rgistration(RegModel input)
{
var user = await _userRegistrationManager.RegisterAsync(input.EmailAddress, input.Password, false );
var result = await _userManager.AddToRoleAsync(user, defaultRoleName);
user.Code = GenerateCode();
await SendEmail(user.EmailAddress, user.Code);
await AddSubEntities(user);
await AddSubCollectionEntities(user);
await CurrentUnitOfWork.SaveChangesAsync();
return user.MapTo<ResponceDto>();
}
private async Task AddSubEntities(User user)
{
var newSubEntity = new newSubEntity { User = user, UserId = user.Id };
await _subEntityRepo.InsertAsync(newSubEntity);
//few another One-to-One entities...
}
private async Task AddSubEntities(User user)
{
List<AnotherEntity> collection = GetSomeCollection(user.Type);
await _anotherEntitieRepo.GetDbContext().AddRangeAsync(collection);
//few another One-to-Many collections...
}
Try change:
public async Task<ResponceDto> Rgistration(RegModel input)
{
var user = await _userRegistrationManager.RegisterAsync(input.EmailAddress, input.Password, false );
Task.Run(async () => {
var result = await _userManager.AddToRoleAsync(user, defaultRoleName);
});
Task.Run(async () => {
user.Code = GenerateCode();
await SendEmail(user.EmailAddress, user.Code);
});
Task.Run(async () => {
using (var unitOfWork = UnitOfWorkManager.Begin())
{//long operation. defalt unitOfWork out of scope
try
{
await AddSubEntities(user);
}
finally
{
unitOfWork.Complete();
}
}
});
Task.Run(async () => {
using (var unitOfWork = UnitOfWorkManager.Begin())
{
try
{
await AddSubCollectionEntities(user);
}
finally
{
unitOfWork.Complete();
}
}
});
await CurrentUnitOfWork.SaveChangesAsync();
return user.MapTo<ResponceDto>();
}
Errors:
here I get a lot of different errors related to competition. frequent:
A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext.
In few registratin calls: Cannot insert duplicate key row in object 'XXX' with unique index 'YYY'. The duplicate key value is (70). The statement has been terminated.
I thought on the server every request in its stream, but apparently not.
or all users are successfully registered, but they don’t have some sub-entity in the database. it’s much easier not to register the user than to figure out where he was initialized incorrectly =(
how to keep the user entity “open” for updating and at the same time “closed” for changes initiated by other requests? How to make this code thread safe and fast, can anyone help with advice?
Using Task.Run in ASP.NET is rarely a good idea.
Async methods run on the thread pool anyway, so wrapping them in Task.Run is simply adding overhead without any benefit.
The purpose of using async in ASP.NET is simply to prevent threads being blocked so they are able to serve other HTTP requests.
Ultimately, your database is the bottleneck; if all these operations need to happen before you return a response to the client, then there's not much you can do other than to let them happen.
If it is possible to return early and allow some operations to continue running on the background, then there are details here showing how that can be done.
Task.Run is not the same as parallel. It takes a new thread from the pool and runs the work on that thread, and since you're not awaiting it, the rest of the code can move on. However, that's because you're essentially orphaning that thread. When the action returns, all the scoped services will be disposed, which includes things like your context. Any threads that haven't finished, yet, will error out as a result.
The thread pool is a limited resource, and within the context of a web application, it equates directly to the throughput of your server. Every thread you take is one less request you can service. As a result, you're more likely to end up queuing requests, which will only add to processing time. It's virtually never appropriate to use Task.Run in a web environment.
Also, EF Core (or old EF, for that matter) does not support parallelization. So, even without the other problems described above, it will stop you cold from doing what you're trying to do here, regardless.
The queries you have here are not complex. Even if you were trying to insert 100s of things at once, it should still take only milliseconds to complete. If there is any significant delay here, you need to look at the resources of your database server and your network latency, first.
More likely than not, the slow-down is coming from the sending of the email. That too can likely be optimized, though. I was in a situation once where it was taking emails 30 seconds to send, until I finally figured out that it was an issue with our Exchange server, where an IT admin had idiotically introduced a 30 second delay on purpose. Regardless, it is generally always preferable to background things like sending emails, since they aren't core to your app's functionality. However, that means actually processing them in background, i.e. queue them and process them via something like a hosted service or an entirely different worker process.

KeyVaultClient hangs at GetSecretAsync [duplicate]

I have a multi-tier .Net 4.5 application calling a method using C#'s new async and await keywords that just hangs and I can't see why.
At the bottom I have an async method that extents our database utility OurDBConn (basically a wrapper for the underlying DBConnection and DBCommand objects):
public static async Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
T result = await Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
return result;
}
Then I have a mid level async method that calls this to get some slow running totals:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Finally I have a UI method (an MVC action) that runs synchronously:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
The problem is that it hangs on that last line forever. It does the same thing if I call asyncTask.Wait(). If I run the slow SQL method directly it takes about 4 seconds.
The behaviour I'm expecting is that when it gets to asyncTask.Result, if it's not finished it should wait until it is, and once it is it should return the result.
If I step through with a debugger the SQL statement completes and the lambda function finishes, but the return result; line of GetTotalAsync is never reached.
Any idea what I'm doing wrong?
Any suggestions to where I need to investigate in order to fix this?
Could this be a deadlock somewhere, and if so is there any direct way to find it?
Yep, that's a deadlock all right. And a common mistake with the TPL, so don't feel bad.
When you write await foo, the runtime, by default, schedules the continuation of the function on the same SynchronizationContext that the method started on. In English, let's say you called your ExecuteAsync from the UI thread. Your query runs on the threadpool thread (because you called Task.Run), but you then await the result. This means that the runtime will schedule your "return result;" line to run back on the UI thread, rather than scheduling it back to the threadpool.
So how does this deadlock? Imagine you just have this code:
var task = dataSource.ExecuteAsync(_ => 42);
var result = task.Result;
So the first line kicks off the asynchronous work. The second line then blocks the UI thread. So when the runtime wants to run the "return result" line back on the UI thread, it can't do that until the Result completes. But of course, the Result can't be given until the return happens. Deadlock.
This illustrates a key rule of using the TPL: when you use .Result on a UI thread (or some other fancy sync context), you must be careful to ensure that nothing that Task is dependent upon is scheduled to the UI thread. Or else evilness happens.
So what do you do? Option #1 is use await everywhere, but as you said that's already not an option. Second option which is available for you is to simply stop using await. You can rewrite your two functions to:
public static Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
return Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
}
public static Task<ResultClass> GetTotalAsync( ... )
{
return this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
}
What's the difference? There's now no awaiting anywhere, so nothing being implicitly scheduled to the UI thread. For simple methods like these that have a single return, there's no point in doing an "var result = await...; return result" pattern; just remove the async modifier and pass the task object around directly. It's less overhead, if nothing else.
Option #3 is to specify that you don't want your awaits to schedule back to the UI thread, but just schedule to the thread pool. You do this with the ConfigureAwait method, like so:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var resultTask = this.DBConnection.ExecuteAsync<ResultClass>(
ds => return ds.Execute("select slow running data into result");
return await resultTask.ConfigureAwait(false);
}
Awaiting a task normally would schedule to the UI thread if you're on it; awaiting the result of ContinueAwait will ignore whatever context you are on, and always schedule to the threadpool. The downside of this is you have to sprinkle this everywhere in all functions your .Result depends on, because any missed .ConfigureAwait might be the cause of another deadlock.
This is the classic mixed-async deadlock scenario, as I describe on my blog. Jason described it well: by default, a "context" is saved at every await and used to continue the async method. This "context" is the current SynchronizationContext unless it it null, in which case it is the current TaskScheduler. When the async method attempts to continue, it first re-enters the captured "context" (in this case, an ASP.NET SynchronizationContext). The ASP.NET SynchronizationContext only permits one thread in the context at a time, and there is already a thread in the context - the thread blocked on Task.Result.
There are two guidelines that will avoid this deadlock:
Use async all the way down. You mention that you "can't" do this, but I'm not sure why not. ASP.NET MVC on .NET 4.5 can certainly support async actions, and it's not a difficult change to make.
Use ConfigureAwait(continueOnCapturedContext: false) as much as possible. This overrides the default behavior of resuming on the captured context.
I was in the same deadlock situation but in my case calling an async method from a sync method, what works for me was:
private static SiteMetadataCacheItem GetCachedItem()
{
TenantService TS = new TenantService(); // my service datacontext
var CachedItem = Task.Run(async ()=>
await TS.GetTenantDataAsync(TenantIdValue)
).Result; // dont deadlock anymore
}
is this a good approach, any idea?
Just to add to the accepted answer (not enough rep to comment), I had this issue arise when blocking using task.Result, event though every await below it had ConfigureAwait(false), as in this example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
The issue actually lay with the external library code. The async library method tried to continue in the calling sync context, no matter how I configured the await, leading to deadlock.
Thus, the answer was to roll my own version of the external library code ExternalLibraryStringAsync, so that it would have the desired continuation properties.
wrong answer for historical purposes
After much pain and anguish, I found the solution buried in this blog post (Ctrl-f for 'deadlock'). It revolves around using task.ContinueWith, instead of the bare task.Result.
Previously deadlocking example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
Avoid the deadlock like this:
public Foo GetFooSynchronous
{
var foo = new Foo();
GetInfoAsync() // ContinueWith doesn't run until the task is complete
.ContinueWith(task => foo.Info = task.Result);
return foo;
}
private async Task<string> GetInfoAsync
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
quick answer :
change this line
ResultClass slowTotal = asyncTask.Result;
to
ResultClass slowTotal = await asyncTask;
why? you should not use .result to get the result of tasks inside most applications except console applications if you do so your program will hang when it gets there
you can also try the below code if you want to use .Result
ResultClass slowTotal = Task.Run(async ()=>await asyncTask).Result;

Task.Wait() on async method works locally, but not via another method

I recently resolved a problem I had while trying to execute an async method. To me, this posed more questions than it solved. In short, I am happy that it works, but I don't know why it does.
I was attempting to run the following method of the Microsoft Graph Client library:
_graphServiceClient.Users[userPrincipalName].Request().GetAsync()
The following approach did not work, as it hangs after using await:
async Task<User> GetUser(string userPrincipalName)
{
User user = await _graphServiceClient.Users[userPrincipalName].Request().GetAsync();
return user;
}
The following approach also did not work, as it hangs after executing runTask.Wait():
User GetUser(string userPrincipalName)
{
return (User) GetResult(_graphServiceClient.Users[userPrincipalName].Request().GetAsync());
}
object GetResult<TResult>(Task<TResult> task)
{
using (task)
using (var runTask = Task.Run(async () => await task))
{
try
{
runTask.Wait();
return runTask.Result;
}
catch (AggregateException e)
{
throw e.InnerException ?? e;
}
}
}
This is where things get weird, as the following code did work:
User GetUser(string userPrincipalName)
{
using (var task = Task.Run(async () => await _graphServiceClient.Users[userPrincipalName].Request().GetAsync()))
{
try
{
task.Wait();
return task.Result;
}
catch (AggregateException e)
{
throw e.InnerException ?? e;
}
}
}
While I realize that the last two approaches are not considered best practice, I am completely puzzled as to why the third approach works, while the second one does not. To me, it looks like these are nearly identical.
So why would the third method work, but not the second one?
First, you need to understand how the deadlock happens. await will (by default) capture a "context" and will resume executing the rest of the async method in that context. In the ASP.NET Classic case, this "context" is a request context, which only allows one thread to run at a time. When running on a thread pool thread, the "context" is a thread pool context, which just queues the rest of the async method to the thread pool, where it can be run by any thread pool thread.
Blocking on asynchronous code is an antipattern. In situations where you have a single-threaded context (e.g., ASP.NET Classic), you can end up in deadlock. In your first deadlocking example, you have GetUser called in the ASP.NET Classic context, so its await will capture that context. Then the calling code (also running in the ASP.NET Classic context) will block on that task. This blocks a thread in that context, which prevents GetUser from completing, so you end up with a deadlock.
But even if you don't end up in deadlock, you still end up throwing away all the benefits of asynchronous code in the first place. Consider the "working" example, which falls into another antipattern (Task.Run on ASP.NET). In this case, Task.Run causes GetAsync to run in the thread pool context, so blocking a thread in the ASP.NET Classic context doesn't deadlock. However, this is also an antipattern.
The proper solution is to go async all the way. Specifically, your controller action should be async and use await when calling asynchronous code. Just pretend that Wait() and Result don't exist, and your code will be much happier.

How can I test to make sure this code is really running async?

I have adapted the following code to attempt to load from a web api from the asp.net code by Wasson.
static public async Task<IEnumerable<T>> ExecuteAsync(HttpClient client, String endPoint)
{
IEnumerable<T> result = null;
HttpResponseMessage response = client.GetAsync(endPoint).Result;
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
var tResult = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<IEnumerable<T>>(tResult);
}
return result;
}
As I have it designed, I think this procedure will run asynchronously, but I am not sure how to test it to make sure it does.
I am new to using asynchronous coding, so any suggestions would be helpful.
The calling procedure is as follows:
public virtual IEnumerable<T> Fill()
{
IEnumerable<T> result = null;
try
{
using (var client = CreateClient("", new MediaTypeWithQualityHeaderValue("application/json")))
{
String _endPoint = "api/" + typeof(T).Name + "/Get";
result = (ExecuteAsync(client, _endPoint)).Result;
}
}
catch (Exception ex)
{
LogError(ex.Message);
}
return result;
}
Is this combination likely to run asynchronously as I want it to?
The reason I want to be able to run it asynchronously is that the Fill routines fetch large amounts of data from a database. It is more a case of a large number of individual records rather than a large size for each record, although the size of some of the records may also be an issue.
What I don't want is the user sitting there waiting for the entire page to load while the communication with the database is occurring.
It doesn't really matter in this case whether I am directly connecting to the database or going through the web api I am using: It takes a long time in some cases either way.
I am also concerned about deadlocks: One large fetch coming in while another is pending.
I initially patterned the code after Mike Wasson's sample code, but found that the code hanged indefinitely even though it compiled.
Does this help frame the situation a little better?
Not sure what you're after here mate.
The code you posted will still block the thread it's on since you're calling Result which will block.
result = (ExecuteAsync(client, _endPoint)).Result;
You could make it asynchronous by letting the async and await keywords spread back to whatever method initially created the request.
public virtual async Task<IEnumerable<T>> Fill()
{
...
result = await ExecuteAsync(client, _endPoint);
...
}
However I'm not sure this really is what you're after since you mention
What I don't want is the user sitting there waiting for the entire page to load while the communication with the database is occurring.
By default, making things asynchronous will not solve this for you. An operation that takes 15 seconds to complete will take 15 seconds to complete regardless of it being synchronous or asynchronous. The difference is that if it's asynchronous then you're being more resource effective (meaning, you'll free up the thread to preform other duties while waiting for something to complete).
However, you can use tasks to achive parallelity. Take for example:
public void DoWork()
{
Thread.Sleep(10000);
}
public void DoMoreWork()
{
Thread.Sleep(10000);
}
If we called these two like this
DoWork();
DoMoreWork();
Then that would take 20000 ms or 20 seconds
And if we make it asynchronous
public async Task DoWork()
{
await Task.Delay(10000);
}
public async Task DoMoreWork()
{
await Task.Delay(10000);
}
and call it like this
await DoWork();
await DoMoreWork();
Then it will STILL take 20 seconds to complete. However, since DoWork and DoMoreWork can operate independent from eachothers we could run them both at the same time by doing
await Task.WhenAll(DoWork(), DoMoreWork());
This would (in a perfect world) result in both tasks being done in 10 seconds halving the time the user has to wait.
Hope I shed some light on the issue :)

multithreading in regards toTask, async, and await

I have the following code and just want to make sure I have the concept of multithreading down on a high level.
public async Task<List<Category>> GetProjectsByCategoryIDAsync(Int16 categoryid)
{
try
{
using (YeagerTechEntities DbContext = new YeagerTechEntities())
{
DbContext.Configuration.ProxyCreationEnabled = false;
DbContext.Database.Connection.Open();
var category = await DbContext.Categories.Include("Projects").Where(p => p.CategoryID == categoryid).ToListAsync();
return category;
}
}
catch (Exception)
{
throw;
}
}
It is my understanding of the following:
async - declares a method to run asynchounously instead of
synchrounously.
Task - declares a method to run as a task on a single thread
await - the task waits for the operation to complete.
Where I am a little fuzzy about is the await keyword. Obviously, the benefit of asynchrounous programming is that the method supposedly doesn't have to wait for the task to complete before another request comes in right behind it. But with the await keyword, the task waits until the operation is finished.
With synchrounous programming, everything is processed in a sequential pattern.
How does this methodology allow for requests to come in simultaneously and be executed in a much faster fashion than synchronous programming??
I just need a high level explanation to get the concept down.
Thanks so much in advance.
Consider the following code:
public async Task DoSomething()
{
Console.WriteLine("Begin");
int i = await DoSomethingElse();
Console.WriteLine("End " + i);
}
public Task<int> DoSomethingElse()
{
return new Task<int>(() =>
{
// do heavy work
Thread.Sleep(1000);
return 1;
});
}
With synchrounous programming, everything is processed in a sequential
pattern.
The code above is asynchronous, but is still sequential. The difference between that code and its synchronous version (e.g., public int DoSomethingElse) is that when you await DoSomethingElse, the main thread will be freed to do other work, instead of blocking waiting for DoSomethingElse to complete.
What actually happens is: your async DoSomething method will run on thread A and be broken in two.
the first part will print "Begin" and make an async call, and then return.
the second part will print "End"
After the first part of the method executes, Thread A will be free to do other work.
Meanwhile, Thread B will be executing the lambda expression that does some heavy work.
Whenever Thread B completes, the second part of your method will be scheduled to run on Thread A, and "End" will be printed.
Notice that, while Thread B was executing the heavy work, Thread A was free to do other stuff.
How does this methodology allow for requests to come in simultaneously
and be executed in a much faster fashion than synchronous
programming??
In frameworks such as ASP.NET MVC, your application has a finite number of threads available to handle incoming requests (lets call these "request threads"). By delegating heavy work to other threads and awaiting, your request threads will be free to handle more incoming requests while heavy work is being done.
This diagram, although complex, illustrates the execution/suspension flow of threads executing asynchronous work:
Notice how at step 6 the thread was yielded, and then step 7 resumed the execution of the method.
As you can see, the await keyword effectively breaks the method in two.

Categories

Resources