I had method, to check count of Landlords шт LandlordTypes
I had this code to check it
var type = _landlordTypeRepository.GetAll()
.Include(x => x.Landlords)
.FirstOrDefault(x => x.Id == input.Id);
if (type.Landlords.Count > 0)
{
throw new UserFriendlyException(L("ThisTypeIsInUse"));
}
But I rewrote it like this
var type = _landlordTypeRepository
.GetAll()
.AnyAsync(x=> x.Id == input.Id && x.Landlords.Any());
But now return type id Task<bool>
How I can use this in if?
You need to use await:
var type = await _landlordTypeRepository.GetAll().AnyAsync(x=> x.Id == input.Id && x.Landlords.Any());
You method must also be marked as async.
I recommend you get acquainted with async - await.
Use await to "unwrap" Task result
bool type = await _landlordTypeRepository.GetAll().AnyAsync(x=> x.Id == input.Id && x.Landlords.Any());
Also mark calling method as async
async Task SomeMethod() {
//..
bool type = await _landlordTypeRepository.GetAll().AnyAsync(x=> x.Id == input.Id && x.Landlords.Any());
//..
}
You can either use the await keyword or simply put .Result at the end of a task to get the value you are looking for.
When using await, your method's signature must have async and must also return a Task (e.g. Task<string> or simply Task for void) unless it's an event which can then be async void.
Using .Result, will block the current thread which means can freeze the UI as well!
A Task is a reference data structure used for asynchronous calls. It contains a .Result-property which will be filled with the return value once the call has completed. Since it is an asynchronous call you cannot know for sure that the call has been completed when receiving a Task the way you have done here.
There is two main ways of dealing with this:
If you're inside an asynchronous context (method using the async keyword), you could just use the await-keyword to wait for and unwrap the result.
var type = await _landlordRepository.GetAll().AnyAsync(...);
If you're in a synchronous context, you can use Task.Wait() to await the call and then read the result value from Task<T>.Result.
var task = _landlordRepository.GetAll().AnyAsync(...).Wait();
var type = task.Result
As people have pointed out, using .Result is usually not advised since it is a blocking call.
Related
I have a bunch of async tasks that may or may not be run based on the results of other expressions. Howerever, I still want to be able to await them all, but I can't do this since some will not be initialized. How can I default initialize a Task? For example:
Task<string> ownerTask;
if(fields.Select(x => x.Name == "owner").Any())
{
ownerTask = _repo.GetOwnerIdFromIssueId(issueId);
}
await Task.WhenAll(ownerTask, anothertask, anothertask, etc);
In this example, "ownerTask" may or may not actually have a task associated with it depending on the result of the if statement, but I don't want to have to block my thread by awaiting the task inside of the if.
Thanks!
Well, you could use a completed task:
Task<string> ownerTask = Task.FromResult("");
Alternatively, you could keep a list of the tasks you actually want to wait for, and only add "real" tasks to that list.
How can I default initialize a Task?
Task.Complete is a task that's completed with no result, and Task.FromResult() is a task that's completed with a result. So you probably want something like:
var ownerTask = fields.Any(x => x.Name == "owner")
? _repo.GetOwnerIdFromIssueId(issueId)
: Task.FromResult((string)null);
But really, you shouldn't even be creating and/or awaiting this task if you know you don't need to. A much better pattern would be something like:
var tasks = new List<Task<string>>();
if(fields.Any(x => x.Name == "owner"))
tasks.Add(_repo.GetOwnerIdFromIssueId(issueId));
// add the others
await Task.WhenAll(tasks);
You should use the Task.WhenAll(IEnumerable<Task> tasks); overload, this way you can await variable count of tasks.
var tasks = new List<Task>();
if(fields.Select(x => x.Name == "owner").Any())
{
tasks.Add(_repo.GetOwnerIdFromIssueId(issueId));
}
tasks.Add(anothertask);
// You could even check if any task is added to the list
// this way you will skip an await.
if(tasks.Count > 0)
await Task.WhenAll(tasks);
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
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!
I have a series of async methods that I would like to execute simultaneously. Each of these methods return true or false in regards to if they execute successfully or not. Their results are also logged in our audit trail so that we can diagnose issues.
Some of my functions are not dependent on all of these methods executing successfully, and we fully expect some of them to fail from time to time. If they do fail, the program will continue to execute and it will merely alert our support staff that they need to correct the issue.
I'm trying to figure out what would be the best method for all of these functions to execute simultaneously, and yet have the parent function await them only after they have all begun to execute. The parent function will return False if ANY of the functions fail, and this will alert my application to cease execution.
My idea was to do something similar to:
public async Task<bool> SetupAccessControl(int objectTypeId, int objectId, int? organizationId)
{
using (var context = new SupportContext(CustomerId))
{
if (organizationId == null)
{
var defaultOrganization = context.Organizations.FirstOrDefault(n => n.Default);
if (defaultOrganization != null) organizationId = defaultOrganization.Id;
}
}
var acLink = AcLinkObjectToOrganiation(organizationId??0,objectTypeId,objectId);
var eAdmin = GrantRoleAccessToObject("eAdmin", objectTypeId, objectId);
var defaultRole = GrantRoleAccessToObject("Default", objectTypeId, objectId);
await acLink;
await eAdmin;
await defaultRole;
var userAccess = (objectTypeId != (int)ObjectType.User) || await SetupUserAccessControl(objectId);
return acLink.Result && eAdmin.Result && defaultRole.Result && userAccess;
}
public async Task<bool> SetupUserAccessControl(int objectId)
{
var everyoneRole = AddToUserRoleBridge("Everyone", objectId);
var defaultRole = AddToUserRoleBridge("Default", objectId);
await everyoneRole;
await defaultRole;
return everyoneRole.Result && defaultRole.Result;
}
Is there a better option? Should I restructure in any way? I'm simply trying to speed up execution time as I have a parent function that executes close to 20 other functions that are all independent of each other. Even at it's slowest, without async, it only takes about 1-2 seconds to execute. However, this will be scaled out to eventually have that parent call executed several hundred times (bulk insertions).
Async methods have a synchronous part which is the part before the first await of an uncompleted task is reached (if there isn't one then the whole method runs synchronously). That part is executed synchronously using the calling thread.
If you want to run these methods concurrently without parallelizing these parts simply invoke the methods, gather the tasks and use Task.WhenAll to await for all of them at once. When all tasks completed you can check the individual results:
async Task<bool> SetupUserAccessControlAsync(int objectId)
{
var everyoneRoleTask = AddToUserRoleBridgeAsync("Everyone", objectId);
var defaultRoleTask = AddToUserRoleBridgeAsync("Default", objectId);
await Task.WhenAll(everyoneRoleTask, defaultRoleTask)
return await everyoneRoleTask && await defaultRoleTask;
}
If you do want to parallelize that synchronous part as well you need multiple threads so instead of simply invoking the async method, use Task.Run to offload to a ThreadPool thread:
async Task<bool> SetupUserAccessControlAsync(int objectId)
{
var everyoneRoleTask = Task.Run(() => AddToUserRoleBridgeAsync("Everyone", objectId));
var defaultRoleTask = Task.Run(() => AddToUserRoleBridgeAsync("Default", objectId));
await Task.WhenAll(everyoneRoleTask, defaultRoleTask)
return await everyoneRoleTask && await defaultRoleTask;
}
If all your methods return bool you can gather all the tasks in a list, get the results from Task.WhenAll and check whether all returned true:
async Task<bool> SetupUserAccessControlAsync(int objectId)
{
var tasks = new List<Task<bool>>();
tasks.Add(AddToUserRoleBridgeAsync("Everyone", objectId));
tasks.Add(AddToUserRoleBridgeAsync("Default", objectId));
return (await Task.WhenAll(tasks)).All(_ => _);
}
I have the following code:
var result = MessageBoxHelper.MsgBox
.ShowAsync("Press Yes to proceed", MessageBoxButton.YesNo)
.ContinueWith((answer) =>
{
if (answer.Result == MessageBoxResult.Yes)
{
Task<bool> asyncTask = ExecuteAsyncFunc();
//asyncTask.Unwrap(); ??
asyncTask.ContinueWith((a) =>
{
// More
}, TaskContinuationOptions.OnlyOnRanToCompletion);
}
}, TaskContinuationOptions.OnlyOnRanToCompletion);
}
Invoked elsewhere like this:
public async Task<bool> ExecuteAsyncFunc()
{
await CallAnotherAsyncFunction();
}
I believe that I need to call Unwrap(), where I have tried to, because I am calling await inside a ContinueWith() block. However, I get the following error when I uncomment it:
Error CS1929 'Task' does not contain a definition for 'Unwrap'
and the best extension method overload
'TaskExtensions.Unwrap(Task)' requires a receiver of type
'Task'
Do I need to use Unwrap in this context, and if so, what am I doing wrong?
The short answer is to use await instead of ContinueWith:
var result = MessageBoxHelper.MsgBox.ShowAsync("Press Yes to proceed", MessageBoxButton.YesNo);
if (answer == MessageBoxResult.Yes)
{
var a = await ExecuteAsyncFunc();
// More
}
The long answer is that ContinueWith has some dangerous default options (including using an ambient TaskScheduler), and await automatically does everything correctly for you. I go into more detail on my blog.
Do I need to use Unwrap in this context, and if so, what am I doing
wrong?
You need to Unwrap only when your return type is a Task<Task>, and you actually want to do something with the inner task.
For example:
Task<Task> exampleTask = Task.Factory.StartNew(async () =>
{
await Task.Delay(1000);
});
If I wanted to actually asynchronously wait on the inner Task, i'd call Unwrap and await on that:
Task exampleTask = await Task.Factory.StartNew(async () =>
{
await Task.Delay(1000);
}).Unwrap();
If for any reason you'd want to await on any task returned from your continuation, or want to monitor the inner task, then you'd call Unwrap. There is no need to do that here.
What you're doing is simply invoking an async method inside your ContinueWith, but it doesn't seem like you want to await the result at all.
I'd recommend using async-await wherever possible to reduce the verbosity of ContinueWith. Mixing those two together usually yields bad results as thing get rather complicated. Refactoring that code ends up much cleaner with much less cyclomatic complexity:
var result = await MessageBoxHelper.MsgBox.ShowAsync("Press Yes to proceed",
MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
bool answer = await ExecuteFuncAsync();
}
You say that you have to call unwrap due to your using await inside the ContinueWith; I don't actually see you using await though. I assume what you meant is that you want to await but are not sure how, and thus thought unwrapping is needed. If that is the case, then what you want is to just make your nested Task awaitable. You can do that by making the delegate you provide async
var result = MessageBoxHelper.MsgBox
.ShowAsync("Press Yes to proceed", MessageBoxButton.YesNo)
.ContinueWith(async (answer) =>
{
if (answer.Result == MessageBoxResult.Yes)
{
await ExecuteAsyncFunc();
}
}, TaskContinuationOptions.OnlyOnRanToCompletion);
public async Task<bool> ExecuteAsyncFunc()
{
await CallAnotherAsyncFunction();
}
This allows you to await within the delegate, within the ContinueWith call and not have to deal with unwrapping.
If you are going to do anything with the Task, such as return it without unwrapping, then this is the right way to go.
public Task<BoolOrSomeOtherReturnType> Foo()
{
return MessageBoxHelper.MsgBox
.ShowAsync /* Continue with etc here */
}
But if you are going to act on the results within the Foo method, then there is no need to use ContinueWith, just await it.
public async Task<bool> Foo()
{
var result = await MessageBoxHelper.MsgBox
.ShowAsync("Press Yes to proceed", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
await ExecuteAsyncFunc();
return true;
}
return false;
}
That simplifies your code quiet a bit. The other thing to note is that your ExecuteAsyncFunc() method does not act on the return value. You simply await and do nothing else.
I noticed that you're not returning true/false, so I assume there is more code there that you just omitted for clarity sake. If that isn't the case, you can save yourself some overhead and just return the Task, allowing someone further up the callstack to await it instead. If your call to CallAnotherAsyncFunction returns Task<bool> then you can just return that call in the same way as well. You only need to await if you have to prevent the method from going any further so you can react to the result of the awaited method. If you don't have to, just return the Task.
public Task<bool> ExecuteAsyncFunc()
{
return CallAnotherAsyncFunction();
}