Asp.Net core 2.1 await doesn't yield control to caller on 2nd run












1














I am in the process of making all of my database operations asynchronous. However, I don't seem to get the desired results of asynchrony.



e.g. -



I am inserting 100 rows to a table in a database in a loop. The function that does this is a async function. It doesn't seem to yield control to its caller when its awaiting. The code is below -



[HttpGet]
[Route("/api/logtest")]
public async Task<JObject> logTestAsync()
{
JObject retval = new JObject();
DateTime dt1 = DateTime.Now;

Task t = BulkLogInsertAsync();


DateTime dt2 = DateTime.Now;
retval["Exec_Time"] = dt2.Subtract(dt1).TotalMilliseconds;

await t;

DateTime dt3 = DateTime.Now;
retval["Await_Time"] = dt3.Subtract(dt2).TotalMilliseconds;
return retval;
}

private async Task BulkLogInsertAsync()
{
List<Task<int>> allTasks = new List<Task<int>>();
for (int i = 0; i<100;i++)
{
allTasks.Add(LogInsertAsync("insert into logs values (getdate() , 'custom' , 'sample message. ', 'Log.bills', 'callsite1', '', '', '')"));
//allTasks.Add(LogInsertAsync("WAITFOR DELAY '00:00:02';"));
}
await Task.WhenAll(allTasks.ToArray()).ConfigureAwait(false);
}
private async Task<int> LogInsertAsync(string cmd)
{
int res = 0;
using (SqlConnection hookup = new SqlConnection(@"[mycnstr]"))
{
Task connectionOpeningTask = hookup.OpenAsync();
using (SqlCommand sqlcmd = new SqlCommand(cmd, hookup))
{
await connectionOpeningTask.ConfigureAwait(false);
res = await sqlcmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
hookup.Close();
}
return res;
}


When I call the API /api/logtest the very first time, I seem to get desired results with exec_time much less than await_time (0.2s vs 4s)



However from 2nd run onwards I get await_time much less than exec_time (4s vs 0.2s) which is making me believe code ran synchronously.



Also the same code in a console app using .net framework 4.6.1, gives desired results continuously. and no I did not restart the console app. Ran the BulkLogInsertAsync in a do while loop :-)



Can anybody please tell me where I am going wrong ?










share|improve this question
























  • you might get help with this link. give it a try stackoverflow.com/questions/25009437/…
    – CodeConstruct
    Nov 12 '18 at 10:47










  • @CodeConstruct thanks for the help, but I think I am chaining the tasks properly here, the problem seems to be with the openAsync and ExecuteNonQueryAsync, somehow , they are not yielding control on subsequent runs.
    – Gaurav Kalele
    Nov 12 '18 at 11:59
















1














I am in the process of making all of my database operations asynchronous. However, I don't seem to get the desired results of asynchrony.



e.g. -



I am inserting 100 rows to a table in a database in a loop. The function that does this is a async function. It doesn't seem to yield control to its caller when its awaiting. The code is below -



[HttpGet]
[Route("/api/logtest")]
public async Task<JObject> logTestAsync()
{
JObject retval = new JObject();
DateTime dt1 = DateTime.Now;

Task t = BulkLogInsertAsync();


DateTime dt2 = DateTime.Now;
retval["Exec_Time"] = dt2.Subtract(dt1).TotalMilliseconds;

await t;

DateTime dt3 = DateTime.Now;
retval["Await_Time"] = dt3.Subtract(dt2).TotalMilliseconds;
return retval;
}

private async Task BulkLogInsertAsync()
{
List<Task<int>> allTasks = new List<Task<int>>();
for (int i = 0; i<100;i++)
{
allTasks.Add(LogInsertAsync("insert into logs values (getdate() , 'custom' , 'sample message. ', 'Log.bills', 'callsite1', '', '', '')"));
//allTasks.Add(LogInsertAsync("WAITFOR DELAY '00:00:02';"));
}
await Task.WhenAll(allTasks.ToArray()).ConfigureAwait(false);
}
private async Task<int> LogInsertAsync(string cmd)
{
int res = 0;
using (SqlConnection hookup = new SqlConnection(@"[mycnstr]"))
{
Task connectionOpeningTask = hookup.OpenAsync();
using (SqlCommand sqlcmd = new SqlCommand(cmd, hookup))
{
await connectionOpeningTask.ConfigureAwait(false);
res = await sqlcmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
hookup.Close();
}
return res;
}


When I call the API /api/logtest the very first time, I seem to get desired results with exec_time much less than await_time (0.2s vs 4s)



However from 2nd run onwards I get await_time much less than exec_time (4s vs 0.2s) which is making me believe code ran synchronously.



Also the same code in a console app using .net framework 4.6.1, gives desired results continuously. and no I did not restart the console app. Ran the BulkLogInsertAsync in a do while loop :-)



Can anybody please tell me where I am going wrong ?










share|improve this question
























  • you might get help with this link. give it a try stackoverflow.com/questions/25009437/…
    – CodeConstruct
    Nov 12 '18 at 10:47










  • @CodeConstruct thanks for the help, but I think I am chaining the tasks properly here, the problem seems to be with the openAsync and ExecuteNonQueryAsync, somehow , they are not yielding control on subsequent runs.
    – Gaurav Kalele
    Nov 12 '18 at 11:59














1












1








1







I am in the process of making all of my database operations asynchronous. However, I don't seem to get the desired results of asynchrony.



e.g. -



I am inserting 100 rows to a table in a database in a loop. The function that does this is a async function. It doesn't seem to yield control to its caller when its awaiting. The code is below -



[HttpGet]
[Route("/api/logtest")]
public async Task<JObject> logTestAsync()
{
JObject retval = new JObject();
DateTime dt1 = DateTime.Now;

Task t = BulkLogInsertAsync();


DateTime dt2 = DateTime.Now;
retval["Exec_Time"] = dt2.Subtract(dt1).TotalMilliseconds;

await t;

DateTime dt3 = DateTime.Now;
retval["Await_Time"] = dt3.Subtract(dt2).TotalMilliseconds;
return retval;
}

private async Task BulkLogInsertAsync()
{
List<Task<int>> allTasks = new List<Task<int>>();
for (int i = 0; i<100;i++)
{
allTasks.Add(LogInsertAsync("insert into logs values (getdate() , 'custom' , 'sample message. ', 'Log.bills', 'callsite1', '', '', '')"));
//allTasks.Add(LogInsertAsync("WAITFOR DELAY '00:00:02';"));
}
await Task.WhenAll(allTasks.ToArray()).ConfigureAwait(false);
}
private async Task<int> LogInsertAsync(string cmd)
{
int res = 0;
using (SqlConnection hookup = new SqlConnection(@"[mycnstr]"))
{
Task connectionOpeningTask = hookup.OpenAsync();
using (SqlCommand sqlcmd = new SqlCommand(cmd, hookup))
{
await connectionOpeningTask.ConfigureAwait(false);
res = await sqlcmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
hookup.Close();
}
return res;
}


When I call the API /api/logtest the very first time, I seem to get desired results with exec_time much less than await_time (0.2s vs 4s)



However from 2nd run onwards I get await_time much less than exec_time (4s vs 0.2s) which is making me believe code ran synchronously.



Also the same code in a console app using .net framework 4.6.1, gives desired results continuously. and no I did not restart the console app. Ran the BulkLogInsertAsync in a do while loop :-)



Can anybody please tell me where I am going wrong ?










share|improve this question















I am in the process of making all of my database operations asynchronous. However, I don't seem to get the desired results of asynchrony.



e.g. -



I am inserting 100 rows to a table in a database in a loop. The function that does this is a async function. It doesn't seem to yield control to its caller when its awaiting. The code is below -



[HttpGet]
[Route("/api/logtest")]
public async Task<JObject> logTestAsync()
{
JObject retval = new JObject();
DateTime dt1 = DateTime.Now;

Task t = BulkLogInsertAsync();


DateTime dt2 = DateTime.Now;
retval["Exec_Time"] = dt2.Subtract(dt1).TotalMilliseconds;

await t;

DateTime dt3 = DateTime.Now;
retval["Await_Time"] = dt3.Subtract(dt2).TotalMilliseconds;
return retval;
}

private async Task BulkLogInsertAsync()
{
List<Task<int>> allTasks = new List<Task<int>>();
for (int i = 0; i<100;i++)
{
allTasks.Add(LogInsertAsync("insert into logs values (getdate() , 'custom' , 'sample message. ', 'Log.bills', 'callsite1', '', '', '')"));
//allTasks.Add(LogInsertAsync("WAITFOR DELAY '00:00:02';"));
}
await Task.WhenAll(allTasks.ToArray()).ConfigureAwait(false);
}
private async Task<int> LogInsertAsync(string cmd)
{
int res = 0;
using (SqlConnection hookup = new SqlConnection(@"[mycnstr]"))
{
Task connectionOpeningTask = hookup.OpenAsync();
using (SqlCommand sqlcmd = new SqlCommand(cmd, hookup))
{
await connectionOpeningTask.ConfigureAwait(false);
res = await sqlcmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
hookup.Close();
}
return res;
}


When I call the API /api/logtest the very first time, I seem to get desired results with exec_time much less than await_time (0.2s vs 4s)



However from 2nd run onwards I get await_time much less than exec_time (4s vs 0.2s) which is making me believe code ran synchronously.



Also the same code in a console app using .net framework 4.6.1, gives desired results continuously. and no I did not restart the console app. Ran the BulkLogInsertAsync in a do while loop :-)



Can anybody please tell me where I am going wrong ?







c# asynchronous async-await asp.net-core-2.1






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 '18 at 10:50









Md. Abdul Alim

349215




349215










asked Nov 12 '18 at 9:27









Gaurav Kalele

916




916












  • you might get help with this link. give it a try stackoverflow.com/questions/25009437/…
    – CodeConstruct
    Nov 12 '18 at 10:47










  • @CodeConstruct thanks for the help, but I think I am chaining the tasks properly here, the problem seems to be with the openAsync and ExecuteNonQueryAsync, somehow , they are not yielding control on subsequent runs.
    – Gaurav Kalele
    Nov 12 '18 at 11:59


















  • you might get help with this link. give it a try stackoverflow.com/questions/25009437/…
    – CodeConstruct
    Nov 12 '18 at 10:47










  • @CodeConstruct thanks for the help, but I think I am chaining the tasks properly here, the problem seems to be with the openAsync and ExecuteNonQueryAsync, somehow , they are not yielding control on subsequent runs.
    – Gaurav Kalele
    Nov 12 '18 at 11:59
















you might get help with this link. give it a try stackoverflow.com/questions/25009437/…
– CodeConstruct
Nov 12 '18 at 10:47




you might get help with this link. give it a try stackoverflow.com/questions/25009437/…
– CodeConstruct
Nov 12 '18 at 10:47












@CodeConstruct thanks for the help, but I think I am chaining the tasks properly here, the problem seems to be with the openAsync and ExecuteNonQueryAsync, somehow , they are not yielding control on subsequent runs.
– Gaurav Kalele
Nov 12 '18 at 11:59




@CodeConstruct thanks for the help, but I think I am chaining the tasks properly here, the problem seems to be with the openAsync and ExecuteNonQueryAsync, somehow , they are not yielding control on subsequent runs.
– Gaurav Kalele
Nov 12 '18 at 11:59












1 Answer
1






active

oldest

votes


















1














Let's set a couple of things straight:




  1. Threads are not magical resources that are just laying there, w8ing for work

  2. The higher number of threads you have, more resources you´ll need to manage them

  3. Asynchrony, although very helpful is not an easy thing


Ok, first of all, your app starts with a predefined number of w8ing threads (usually number of cores*2, if i recall correctly, can find the damn msdn article). If you request threads and you´re using under this limit, you get them instantaneously, otherswise, you'll have to w8 500ms (cant find the article)



Second, async is not parallel!



Third, in your code, whenever you use await, it awaits! so, i suggest you refactor await on OpenAsync, chaining with ContinueWith and only use the await once in your code, because, as it is right now, your using's are preventing async from working properly... you will have to manage the connections and disposals on your own if you want the code to run asynchronously



Edit1:



There are 2 types of threads: IO Threads and Worker threads. In your code, what you need is IO threads to w8 for the database... if you need more context on this, you can start here






share|improve this answer























  • ConfigureAwait is useless in ASP.NET Core: ASP.NET Core SynchronizationContext
    – Paulo Morgado
    Nov 12 '18 at 22:02










  • How are the using's preventing async from working properly?
    – Paulo Morgado
    Nov 12 '18 at 22:03










  • I still don't get it why then the very first time I run this code, I get the desired result, exec_time much less than await_time. The code behaves in a perfect async way, it yields to calling function on await, its only on 2nd time and onwards, the await doesn't yeild to caller.
    – Gaurav Kalele
    Nov 22 '18 at 18:13












  • also not to mention that code works perfectly fine and as expected in a console application !
    – Gaurav Kalele
    Nov 22 '18 at 18:22











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53259193%2fasp-net-core-2-1-await-doesnt-yield-control-to-caller-on-2nd-run%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Let's set a couple of things straight:




  1. Threads are not magical resources that are just laying there, w8ing for work

  2. The higher number of threads you have, more resources you´ll need to manage them

  3. Asynchrony, although very helpful is not an easy thing


Ok, first of all, your app starts with a predefined number of w8ing threads (usually number of cores*2, if i recall correctly, can find the damn msdn article). If you request threads and you´re using under this limit, you get them instantaneously, otherswise, you'll have to w8 500ms (cant find the article)



Second, async is not parallel!



Third, in your code, whenever you use await, it awaits! so, i suggest you refactor await on OpenAsync, chaining with ContinueWith and only use the await once in your code, because, as it is right now, your using's are preventing async from working properly... you will have to manage the connections and disposals on your own if you want the code to run asynchronously



Edit1:



There are 2 types of threads: IO Threads and Worker threads. In your code, what you need is IO threads to w8 for the database... if you need more context on this, you can start here






share|improve this answer























  • ConfigureAwait is useless in ASP.NET Core: ASP.NET Core SynchronizationContext
    – Paulo Morgado
    Nov 12 '18 at 22:02










  • How are the using's preventing async from working properly?
    – Paulo Morgado
    Nov 12 '18 at 22:03










  • I still don't get it why then the very first time I run this code, I get the desired result, exec_time much less than await_time. The code behaves in a perfect async way, it yields to calling function on await, its only on 2nd time and onwards, the await doesn't yeild to caller.
    – Gaurav Kalele
    Nov 22 '18 at 18:13












  • also not to mention that code works perfectly fine and as expected in a console application !
    – Gaurav Kalele
    Nov 22 '18 at 18:22
















1














Let's set a couple of things straight:




  1. Threads are not magical resources that are just laying there, w8ing for work

  2. The higher number of threads you have, more resources you´ll need to manage them

  3. Asynchrony, although very helpful is not an easy thing


Ok, first of all, your app starts with a predefined number of w8ing threads (usually number of cores*2, if i recall correctly, can find the damn msdn article). If you request threads and you´re using under this limit, you get them instantaneously, otherswise, you'll have to w8 500ms (cant find the article)



Second, async is not parallel!



Third, in your code, whenever you use await, it awaits! so, i suggest you refactor await on OpenAsync, chaining with ContinueWith and only use the await once in your code, because, as it is right now, your using's are preventing async from working properly... you will have to manage the connections and disposals on your own if you want the code to run asynchronously



Edit1:



There are 2 types of threads: IO Threads and Worker threads. In your code, what you need is IO threads to w8 for the database... if you need more context on this, you can start here






share|improve this answer























  • ConfigureAwait is useless in ASP.NET Core: ASP.NET Core SynchronizationContext
    – Paulo Morgado
    Nov 12 '18 at 22:02










  • How are the using's preventing async from working properly?
    – Paulo Morgado
    Nov 12 '18 at 22:03










  • I still don't get it why then the very first time I run this code, I get the desired result, exec_time much less than await_time. The code behaves in a perfect async way, it yields to calling function on await, its only on 2nd time and onwards, the await doesn't yeild to caller.
    – Gaurav Kalele
    Nov 22 '18 at 18:13












  • also not to mention that code works perfectly fine and as expected in a console application !
    – Gaurav Kalele
    Nov 22 '18 at 18:22














1












1








1






Let's set a couple of things straight:




  1. Threads are not magical resources that are just laying there, w8ing for work

  2. The higher number of threads you have, more resources you´ll need to manage them

  3. Asynchrony, although very helpful is not an easy thing


Ok, first of all, your app starts with a predefined number of w8ing threads (usually number of cores*2, if i recall correctly, can find the damn msdn article). If you request threads and you´re using under this limit, you get them instantaneously, otherswise, you'll have to w8 500ms (cant find the article)



Second, async is not parallel!



Third, in your code, whenever you use await, it awaits! so, i suggest you refactor await on OpenAsync, chaining with ContinueWith and only use the await once in your code, because, as it is right now, your using's are preventing async from working properly... you will have to manage the connections and disposals on your own if you want the code to run asynchronously



Edit1:



There are 2 types of threads: IO Threads and Worker threads. In your code, what you need is IO threads to w8 for the database... if you need more context on this, you can start here






share|improve this answer














Let's set a couple of things straight:




  1. Threads are not magical resources that are just laying there, w8ing for work

  2. The higher number of threads you have, more resources you´ll need to manage them

  3. Asynchrony, although very helpful is not an easy thing


Ok, first of all, your app starts with a predefined number of w8ing threads (usually number of cores*2, if i recall correctly, can find the damn msdn article). If you request threads and you´re using under this limit, you get them instantaneously, otherswise, you'll have to w8 500ms (cant find the article)



Second, async is not parallel!



Third, in your code, whenever you use await, it awaits! so, i suggest you refactor await on OpenAsync, chaining with ContinueWith and only use the await once in your code, because, as it is right now, your using's are preventing async from working properly... you will have to manage the connections and disposals on your own if you want the code to run asynchronously



Edit1:



There are 2 types of threads: IO Threads and Worker threads. In your code, what you need is IO threads to w8 for the database... if you need more context on this, you can start here







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 12 '18 at 13:16

























answered Nov 12 '18 at 12:38









Leonardo

4,28343387




4,28343387












  • ConfigureAwait is useless in ASP.NET Core: ASP.NET Core SynchronizationContext
    – Paulo Morgado
    Nov 12 '18 at 22:02










  • How are the using's preventing async from working properly?
    – Paulo Morgado
    Nov 12 '18 at 22:03










  • I still don't get it why then the very first time I run this code, I get the desired result, exec_time much less than await_time. The code behaves in a perfect async way, it yields to calling function on await, its only on 2nd time and onwards, the await doesn't yeild to caller.
    – Gaurav Kalele
    Nov 22 '18 at 18:13












  • also not to mention that code works perfectly fine and as expected in a console application !
    – Gaurav Kalele
    Nov 22 '18 at 18:22


















  • ConfigureAwait is useless in ASP.NET Core: ASP.NET Core SynchronizationContext
    – Paulo Morgado
    Nov 12 '18 at 22:02










  • How are the using's preventing async from working properly?
    – Paulo Morgado
    Nov 12 '18 at 22:03










  • I still don't get it why then the very first time I run this code, I get the desired result, exec_time much less than await_time. The code behaves in a perfect async way, it yields to calling function on await, its only on 2nd time and onwards, the await doesn't yeild to caller.
    – Gaurav Kalele
    Nov 22 '18 at 18:13












  • also not to mention that code works perfectly fine and as expected in a console application !
    – Gaurav Kalele
    Nov 22 '18 at 18:22
















ConfigureAwait is useless in ASP.NET Core: ASP.NET Core SynchronizationContext
– Paulo Morgado
Nov 12 '18 at 22:02




ConfigureAwait is useless in ASP.NET Core: ASP.NET Core SynchronizationContext
– Paulo Morgado
Nov 12 '18 at 22:02












How are the using's preventing async from working properly?
– Paulo Morgado
Nov 12 '18 at 22:03




How are the using's preventing async from working properly?
– Paulo Morgado
Nov 12 '18 at 22:03












I still don't get it why then the very first time I run this code, I get the desired result, exec_time much less than await_time. The code behaves in a perfect async way, it yields to calling function on await, its only on 2nd time and onwards, the await doesn't yeild to caller.
– Gaurav Kalele
Nov 22 '18 at 18:13






I still don't get it why then the very first time I run this code, I get the desired result, exec_time much less than await_time. The code behaves in a perfect async way, it yields to calling function on await, its only on 2nd time and onwards, the await doesn't yeild to caller.
– Gaurav Kalele
Nov 22 '18 at 18:13














also not to mention that code works perfectly fine and as expected in a console application !
– Gaurav Kalele
Nov 22 '18 at 18:22




also not to mention that code works perfectly fine and as expected in a console application !
– Gaurav Kalele
Nov 22 '18 at 18:22


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53259193%2fasp-net-core-2-1-await-doesnt-yield-control-to-caller-on-2nd-run%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Lugert, Oklahoma