0

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 ?

1

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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); ... } 

3 Comments

Can you show me how to mark the method invocation async ? And I have already marked the method definition as async Task<IEnumerable<ChapterCodeValidationOutput>> right ? What is missing ?
You did it in the validateChapterCodeDetails method but you also have to do the same with the method where you call await Task.WhenAll(_validChapterCodesTask);
how can you for a variable ? You mean something like async _validChapterCodesTask ... that obviously errors out . Please help with the correct syntax.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.