Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing async version of a sync method: How to return Task<int> which is constant 1?

I have a sync method, now I would like to implement its async version. Fortunately the underlying call already have an async version (dbSet.SaveChangesAsync()), however in my algorithm there is an if branch returning with constant literal 1.

I do not know how to implement this part in the async version?

Sync version:

    public virtual int Add(T entity)
    {
        SetLogContext(entity, _logctx);
        dbSet.Add(entity);

        if (isAutonomous)
        {
            return ctx.SaveChanges();
        }
        return 1;
    }

Async version:

    public virtual Task<int> AddAsync(T entity)
    {
        SetLogContext(entity, _logctx);
        dbSet.Add(entity);

        if (isAutonomous)
        {
            return ctx.SaveChangesAsync();
        }
        return ??? // What to write here?
    }
like image 363
g.pickardou Avatar asked May 21 '15 07:05

g.pickardou


People also ask

How do I return a Task in async?

If you use a Task return type for an async method, a calling method can use an await operator to suspend the caller's completion until the called async method has finished. In the following example, the WaitAndApologizeAsync method doesn't contain a return statement, so the method returns a Task object.

Is an async method that returns Task a return keyword?

DoSomething()' is an async method that returns 'Task', a return keyword must not be followed by an object expression.

Can async return void?

In short, if your async method is an event handler or a callback, it's ok to return void .

What is the return type of async await?

The behavior of async / await is similar to combining generators and promises. Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.


3 Answers

Use

return Task.FromResult(1);
like image 126
General-Doomer Avatar answered Oct 19 '22 11:10

General-Doomer


You have two possibilities how to achieve your needs: one is to use the async keyword:

public virtual async Task<int> AddAsync<T>(T entity)
{
    SetLogContext(entity, _logctx);
    dbSet.Add(entity);

    if (isAutonomous)
    {
        return await ctx.SaveChangesAsync();
    }
    return 1;
}

The other is to use Task.FromResult(1) at the point where you want to return the number.

like image 30
Michael Mairegger Avatar answered Oct 19 '22 13:10

Michael Mairegger


The problem I see here is that you've created an "Async" method that isn't actually async. This could be pretty misleading for the next guy using it.

As @xxMUROxx already mentioned, an "Async" method should be prefixed with the async keyword.

    public virtual async Task<int> AddAsync<T>(T entity)
    {
        SetLogContext(entity, _logctx);
        dbSet.Add(entity);

        if (isAutonomous)
        {
            return await ctx.SaveChangesAsync();
        }
        return 1;
    }

The whole point of using the async await pattern is to change the way the program flows through methods. When the await keyword is hit, the method returns to the caller and usually flows all the way back to the original caller. Typically that'll be an async void event handler like a button click.

When this happens, it allows the calling thread to continue executing while it's waiting for a long running operation to complete. After the long running operation completes the code will create a continuation and continue executing any other code that depends on the result returned.

By omitting the async keyword from the method, you've effectively made the call synchronous again. Defeating the purpose of calling SaveChangesAsync in the first place.

like image 42
craftworkgames Avatar answered Oct 19 '22 13:10

craftworkgames