Merge asyc method into one task

419 views Asked by At

Not sure if this is possible or if it already does something simpler with chained tasks internally, could not work it out from the info I read.

public async Task<ClaimsIdentity> CreateIdentity(string userid )
{
    Guid gid = Guid.Parse(userid);
    Avatar avatar = await _dbContext.Users.Where(d => d.Id == gid).FirstOrDefaultAsync();
    return await CreateIdentity(avatar);
}

public async Task<ClaimsIdentity> CreateIdentity(Avatar avatar)
{
    var identity = new ClaimsIdentity(await GetClaims(avatar)); 
    return identity;
}  
public async Task<List<Claim>> GetClaims(Avatar avatar)
{ 
    var claims = new List<Claim>(); 
    claims = async //(database call to get claims) 
    return claims; 
} 

With above code or any other similar async code, what I'm wondering is there any way to say, continue into, or continue with. So, instead of ending up with three tasks, they could be combined so there is a single state machine either two of methods or even all three?

I'm not sure if it matters that much, just looking for correct way of do it.

eg. (not valid code i know)

public async Task<ClaimsIdentity> CreateIdentity(string userid )
{
    Guid gid = Guid.Parse(userid);
    Avatar avatar = await _dbContext.Users.Where(d => d.Id == gid).FirstOrDefaultAsync();
    return contiuneinto CreateIdentity(avatar);
}

^ say something like that. so the next method would be in same task. seems such waste to create another task for something so little.

1

There are 1 answers

7
i3arnon On BEST ANSWER

Each async method gets its own state-machine and task, you can't automagically combine them.

You can remove both the async and await and use Task.ContinueWith which removes the state-machine, but it does still create a new task:

public Task<ClaimsIdentity> CreateIdentity(string userid )
{
    Guid gid = Guid.Parse(userid);
    return _dbContext.Users.Where(d => d.Id == gid).FirstOrDefaultAsync().
        ContinueWith(avatarTask => CreateIdentity(avatarTask.GetAwaiter().GetResult()));
}

The simplest way to cut back on these tasks and state-machines is to simply join these async methods together, for example:

public async Task<ClaimsIdentity> CreateIdentity(string userid )
{
    Guid gid = Guid.Parse(userid);
    Avatar avatar = await _dbContext.Users.Where(d => d.Id == gid).FirstOrDefaultAsync();
    var claims = new List<Claim>(); 
    claims = async //(database call to get claims) 
    return new ClaimsIdentity(claims);
}

In any case, you don't need to worry about it. The cost of that task creation is probably negligble comapred to your actual asynchronous operations.