Why cant I use await? - c#

I'm working with Identity 2.0 in MVC5, and I'm trying to get the first role for the current user.
This bit of code doesn't report any errors:
var DatabaseContext = new ApplicationDbContext();
var thisUserAccount = DatabaseContext.Users.FirstAsync(u => u.Id == Id);
This bit of code:
var DatabaseContext = new ApplicationDbContext();
var thisUserAccount = await DatabaseContext.Users.FirstAsync(u => u.Id == Id);
reports the following error:
The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'
The method is an asynchronous method, so why cant I use "await"?
Also, will calling:
DatabaseContext.Users.Load();
before the FirstAsync optimise things a bit (rather than building a ToList which I'm assuming FirstSync does)?
I'm still trying to get to grips with what the async stuff can do, so any useful links will be much appreciated.

You need to mark the method that's using await as being async:
async Task<UserAccount> DoStuff()
{
var DatabaseContext = new ApplicationDbContext();
var thisUserAccount = await DatabaseContext.Users.FirstAsync(u => u.Id == Id);
return thisUserAccount;
}
That's what the error message is telling you.

The following characteristics summarize what makes a method async (your missing the first).
The method signature includes an async modifier.
Note: The name of an async method, by convention, ends with an "Async" suffix.
The return type is one of the following types:
Task<TResult> if your method has a return statement in which the
operand has type TResult.
Task if your method has no return statement or has a return statement with no operand.
Void if you're writing an async event handler.
The following link provides a good overview of asynchronous programming using async and await:
http://msdn.microsoft.com/en-us/library/hh191443.aspx

Related

System.InvalidOperationException: 'Invalid operation. The connection is closed.'

I am using .net core 6.0. I am getting this error when I am calling same method from different places. I tried calling this method GetEmployeeByEmployeeNumber from inside Index and I dont get any error and the method returns the object employee with value values populated in employee
public async Task<IActionResult> Index()
{
EmployeeInfo employee = await _employeeService.GetEmployeeByEmployeeNumber(up.EmployeeId);
PopulatePDFDoc();
return View();
}
public async Task<EmployeeInfo?> GetEmployeeByEmployeeNumber(string employeeId)
{
List<int> emplyoeeInfoId = new List<int>();
UserPrincipal up = utilities.UserADIdentity.GetADUserInfo(WindowsIdentity.GetCurrent().Name.ToString());
emplyoeeInfoId = _ackContext.EmployeeInfos.Where(e => e.EmployeeNumber == employeeId).OrderBy(e => e.DateFormFilled).Select(e => e.EmployeeInfoId).ToList();
var employee = await _ackContext.EmployeeInfos.Include(e => e.EmergencyInfos.Where(p => p.EmployeeInfoId.Equals(emplyoeeInfoId.LastOrDefault()))).Where(e=>e.EmployeeInfoId.Equals(emplyoeeInfoId.LastOrDefault())).FirstOrDefaultAsync();
return employee;
}
If I call the same method GetEmployeeByEmployeeNumber from inside PopulatePDFDoc(); then I get an error saying System.InvalidOperationException: 'Invalid operation. The connection is closed.'
below is my PopulatePDFDoc
public async void PopulatePDFDoc()
{
AckPackage.Data.PDFPopulate.DocPDF doc = new Data.PDFPopulate.DocPDF();
EmployeeInfo employee = await _employeeService.GetEmployeeByEmployeeNumber(up.EmployeeId);
}
below is the screen shot of the error:
I am new to .net core. Any help on this will be highly appreciated.
You need to await the call to PopulatePDFDoc() inside the Index method.
Like this:
await PopulatePDFDoc();
Always use await when calling an async method!
The reason you’re getting a “connection closed” error, is because the call to PopulatePDFDoc() is not being “awaited”, and the server request ends before the asynchronous method can run.
Also, PopulatePDFDoc() should return Task instead of void, like this:
public async Task PopulatePDFDoc()
Another thing I noticed that may cause you issues is your _ackContext which looks like it's a class-wide member variable based on the snippet you shared, meaning that same context-instance is shared between multiple methods.
However the context itself is actually not "thread safe", as can be read in Microsofts documentation here: https://learn.microsoft.com/en-us/ef/ef6/fundamentals/working-with-dbcontext which means that if multiple async methods use the same context - which they do in your example - you may run into issues.
The recommended approach is to create the context when you need it, and use the using syntax to make sure it's disposed properly after your work is finished. Like this:
using (var ackContext = new EmployeeContext())
{
// Perform data access using the context here
}
Try using that in your GetEmployeeByEmployeeNumber method and see if it helps as well :)

Handle result returned by async call within async method

Imagine this is a method performing a DB query and returning a result, which in case of null is replaced with a default value (Null object pattern).
public ResultObj Get()
{
var result = dbContext.GetSomeResult();
return result ?? ResultObj.NullValue;
}
Imagine this DB query is a long-running process, so I would use async/await to execute this process in a separate thread. Suppose that the dbContext.GetSomeResultAsync() method is available.
How can be this method converted in an asynchronous one so that I can write something like this?
var resultTask = GetAsync();
var otherResultTask = GetSomethingElseAsync();
Task.WaitAll(resultTask, otherResultTask);
var myResult = resultTask.Result;
var myOtherResult = otherResultTask.Result;
I tried this solution.
public async Task<ResultObj> GetAsync()
{
var result = await dbContext.GetSomeResultAsync();
return result ?? ResultObj.NullValue;
}
First, I'm wondering why this code compiles: why can I return ResultObj when Task<ResultObj> is expected?
Second, this code predictably results in a deadlock, as clearly explained by the great number of resources about async deadlocks anti-patterns. The deadlock can be prevented by using .ConfigureAwait(false) method after the async call. Is this the right way to go? Are there any hidden drawbacks in this case? Is it a general rule?
I also tried this.
public async Task<ResultObj> GetAsync()
{
return await Task.Run(() => {
var result = dbContext.GetSomeResult();
return result ?? ResultObj.NullValue;
});
}
This results in a deadlock, too. This time I cannot even figure out why.
Edit: possible solution
Finally, after having read this, I found a solution to my problem.
My generic query wrapper method is like this.
public async Task<ResultObj> GetAsync()
{
var result = await dbContext.GetSomeResultAsync();
return result ?? ResultObj.NullValue;
}
On calling method, I use this pattern.
public async Task<CollectedResults> CollectAsync()
{
var resultTask = GetAsync();
var otherResultTask = GetSomethingElseAsync();
//here both queries are being executed.
//...in the while, optionally, here some other synchronous actions
//then, await results
var result = await resultTask;
var otherResult = await otherResultTask;
//here process collected results and return
return new CollectedResults(...);
}
It is worth mentioning that the above code, wrapped in a domain class, is called by a Controller action. In order for this to work I had to make async the methods all the way up, until Controller action, which now appears as follows.
public async Task<CollectedResults> Get()
{
return await resultsCollector.CollectAsync();
}
This way, deadlock doesn't happen anymore and execution time greatly improves with respect to the synchronous version.
I don't know if this is the canonical way of executing parallel queries. But it works and I don't see particular pitfalls in the code.
First of all, regarding :
so I would use async/await to execute this process in a separate thread.
There is no new thread created when we use async and await
Secondly:
why can I return ResultObj when Task is expected?
the Task<TResult> as return type of method tells that it returns a Task of type TResult but we need to return object of type that TResult back from it so the method can be awaited and when using Task<TResult> as reutrn type we should be using async and await to do the work.
Lastly:
this code predictably results in a deadlock
You are using async keyword with method signatures and also await the next async method call being done from within the method. So apparently it looks like the code in first example you have posted shouldn't be deadlocked, if the method GetSomeResultAsync you are consuming is really a async method and is properly implemented.
I suggest to study more about the async await before getting in to it, following is a good article to start with:
https://blog.stephencleary.com/2012/02/async-and-await.html

Best practice - warning: method lacks 'await' operator warning

Yes, I know there are other questions to cover what this warning means and how to solve it, however, I have a question about best practices regarding async programming.
I have a service layer which handles data transfer between the data layer and the presentation layer. This service contains several methods which query the database, and return the result.
I have been trying to use async programming wherever possible. An example:
public async Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
{
return await Database.FindBy<SiteTemplateResource>(str => str.SiteTemplateId == siteTemplateId && str.HashedFile.EndsWith(extension)).ToArrayAsync();
}
My problem with this is, I'm not actually awaiting anything, other than to the ToArrayAsync call, which I don't really need.
Should I go ahead and use async/await for this? And how would I for example await anything for this function:
public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
{
return Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId;
}
I don't await anything in that function, but I also don't need to call ToArrayAsync, so how do I avoid the warning "method lacks 'await' operator" in above case?
Thanks in advance.
If you have nothing to await in a method that needs to be async (for whatever reason), you can use Task.FromResult, which can be awaited:
public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
{
return await Task.FromResult(Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId);
}
If you don't need the async method, you can simply more the async Task<int> and replace it for int.
Asynchornous api does not necessary need async\await keywords. First you should ask yourself if anything you call inside your method use IO and have asynchronous version of that IO api. In your case you try to access database, that is IO, your library has asynchronous version (ToArrayAsync), so all makes sense. Now check if you do anything else after calling that asynchronous api. If yes - use async\await. If not - just return the result back to the caller:
public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
{
return Database.FindBy<SiteTemplateResource>(str => str.SiteTemplateId == siteTemplateId && str.HashedFile.EndsWith(extension)).ToArrayAsync();
}
In the second case you also try to access database, but you think that there is no async api to do that. Most likely that is not true, because if you have ToArrayAsync - it's very likely all database access methods have async version and so you should have FirstAsync. Then your method becomes:
public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
{
var result = await Database.FirstAsync<SiteSiteTemplate>(sst => sst.SiteId == siteId);
return result.SiteTemplateId;
}
Here you do something after calling FirstAsync, so you need to use async\await keywords.
async/await are needed only if you want to process the results of an already asynchronous operation in the method itself. They don't make the method or the call asynchronous. If you don't need to process the Task result, you can just return it:
public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
{
return Database.FindBy<SiteTemplateResource>(str =>
str.SiteTemplateId == siteTemplateId
&& str.HashedFile.EndsWith(extension))
.ToArrayAsync();
}
or, using an expression bodied method
public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)=>
Database.FindBy<SiteTemplateResource>(str =>
str.SiteTemplateId == siteTemplateId
&& str.HashedFile.EndsWith(extension))
.ToArrayAsync();
You can avoid async/await in the second case as well and still keep it asynchronous, if you use Where,Select and FirstAsync:
public Task<int> SiteTemplateBySiteIdAsync(int siteId)=>
Database.Where(sst => sst.SiteId == siteId)
.Select(it=>it.SiteTemplateId)
.FirstAsync();
}
This has the added advantage of returning only the ID from the database. If you didn't use Select, the provider would have to read the entire object
Maybe you can change your code like bellow:
public int SiteTemplateBySiteIdAsync(int siteId)
{
return Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId;
}
Have a nice day!

Running multiple tasks asynchronously and awaiting for their results c#

In my service layer I wanted to fire multiple methods asynchronously and await for their results.
I tried with one at a time and it is erroring out.
In my service class I called the method like
var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = await _validChapterCodesTask;
And in DAL class the method definition looks like
public async Task<IEnumerable<ChapterCodeValidationOutput>> validateChapterCodeDetails(GroupMembershipValidationInput gmvi)
{
Repository rep = new Repository();
if (!gmvi._chapterCodes.All(x => x.Equals("")))
{
var _validChapterCodes = await rep.ExecuteStoredProcedureAsync<Entities.Upload.ChapterCodeValidationOutput>(SQL.Upload.UploadValidation.getChapterCodeValidationSQL(gmvi._chapterCodes),null);
return _validChapterCodes;
}
else
return new List<ChapterCodeValidationOutput>();
}
Error message
Error 208 The await operator can only be used within an async method. Consider marking this method with the async modifier and changing its return type to Task<ARC.Donor.Business.Upload.GroupMembershipValidationOutput>. C:\Users\m1034699\Desktop\Stuart_Upgrade_2.1_New Approach\Stuart_Export_Upload_v2.1\Stuart Web Service\ARC.Donor.Service\Upload\UploadValidationServices.cs 34 13 ARC.Donor.Service
in lines
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = await _validChapterCodesTask;
What am I doing wrong ?
The error message is very explicit. It is telling you that you're Service class method is incorrectly attempting to use the async keyword. In order to fix this, you should be using "Async all the way" as defined in Stephen Cleary's post on MSDN as a best practice.
For example, if you're service class has a method body that is working with Task or Task<T>, or attempting to use the await keyword the method signature for this corresponding method body must be async (as the async keyword enables a method to use the await keyword). Additionally this method itself should also be Task or Task<T> returning, with very few exceptions to that rule.
Personally, I would alter your DAL class to simply return the operation that represents the asynchronous work without actually awaiting it. If you think about it, the body of the validateChapterCodeDetails method does not actually need to do anything with the results, it just needs to return them (instead of materializing them there). Consider the following:
public Task<IEnumerable<ChapterCodeValidationOutput>>
validateChapterCodeDetails(GroupMembershipValidationInput gmvi)
{
var rep = new Repository();
return gmvi._chapterCodes.All(x => x.Equals(""))
? new List<ChapterCodeValidationOutput>()
: rep.ExecuteStoredProcedureAsync
<Entities.Upload.ChapterCodeValidationOutput>
(SQL.Upload.UploadValidation
.getChapterCodeValidationSQL(gmvi._chapterCodes),null)
}
Since your Task<IEnumerable<ChapterCodeValidationOutput>> variable has already been awaited, you can access the .Result property to get what you're looking for.
Then in your Service class your method would look like this:
public async Task ConsumeAsync()
{
var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = _validChapterCodesTask.Result;
// Do something with it...
}
Here is a .NET fiddle that should help to exemplify this for you better.
NOTE
I would also caution using IEnumerable as it pertains to your repo, you should ensure that the results from the Database are not occurring via deferred execution, otherwise you risk the potential for connection issues, i.e.; unintentionally leaving a connection open, or not properly closing one.
In the Service class where you call
var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = await _validChapterCodesTask;
add a async to the method signature where await Task.WhenAll(_validChapterCodesTask); is called. And when this method also has a return type you have to wrap this type in a Task like the exception shows:
Task<ARC.Donor.Business.Upload.GroupMembershipValidationOutput>
E.g. if you have the following method:
public GroupMemberShipValidationOutput validate(..) {
...
await Task.WhenAll(_validChapterCodesTask);
...
}
You have to change the method signature to:
public async Task<GroupMemberShipValidationOutput> validate(..) {
...
await Task.WhenAll(_validChapterCodesTask);
...
}

Cannot convert lambda expression to type "..." because it is not a delegate type

Good day!
I am trying to write an anonymous method using lambda expressions which would return an object from an async task. I would like to do this in the constructor, so that is the reason I can't make its parent method async.
The ReadJsonAsync method returns a Session object.
I will show you the relevant code:
Session session;
fileService = new FileService();
session = async () => { return await fileService.ReadJsonAsync() };
Thanks in advance!
If you want an Anonymous Method, you'll have to declare one which returns a Task<Session> as it is marked with the async modifier, hence must return a void (only for async event handlers), Task or Task<T> :
Func<Task<Session>> anonFunction = async () => await fileService.ReadJsonAsync();
If all you do is run ReadJsonAsync, you may also save yourself the state machine generation like so:
Func<Task<Session>> anonFunction = fileService.ReadJsonAsync;
Then you can await on it higher up the call stack:
Func<Task<Session>> anonFunction = fileService.ReadJsonAsync;
await anonFunction();
To add to Yuval's useful answer, if you just want to await an inline function, then the magic syntax is:
await ((Func<Task>)(async () =>
{
//async function code
}
))();
Note the extra brackets on the end to call the lambda immediately after declaration. Obviously if your function returns a type, then it would be Func<Task<Whatever>>
Useful if you're using Task.WhenAny() for example to await both an inline function and a timeout task.

Categories