5

Starting with a synchronous I/O bound method (below), how do I make it asynchronous using async/await?

public int Iobound(SqlConnection conn, SqlTransaction tran)
{
    // this stored procedure takes a few seconds to complete
    SqlCommand cmd = new SqlCommand("MyIoboundStoredProc", conn, tran);
    cmd.CommandType = CommandType.StoredProcedure;

    SqlParameter returnValue = cmd.Parameters.Add("ReturnValue", SqlDbType.Int);
    returnValue.Direction = ParameterDirection.ReturnValue;
    cmd.ExecuteNonQuery();

    return (int)returnValue.Value;
}

MSDN examples all presume the preexistence of an *Async method and offer no guidance for making one yourself for I/O-bound operations.

I could use Task.Run() and execute Iobound() within that new Task, but new Task creation is discouraged since the operation is not CPU-bound.

I'd like to use async/await but I'm stuck here on this fundamental problem of how to proceed with the conversion of this method.

6
  • 4
    Why not just use ExecuteNonQueryAsync()? Commented Nov 26, 2017 at 19:46
  • 2
    Please use a using on your SqlCommand... Commented Nov 26, 2017 at 19:47
  • do a google search , there are actually plenty of examples on how to decorate your method to be await as well as use Task<> Commented Nov 26, 2017 at 19:49
  • @CamiloTerevinto may I ask you why you constantly editing formatting of my answer? Position of { (on new line or not) is personal preference and changing it does not add any value. Commented Nov 26, 2017 at 20:32
  • @Evk It's not personal preference if there's a difference between being able to read and having to scroll Commented Nov 26, 2017 at 20:33

1 Answer 1

7

Conversion of this particular method is pretty straight-forward:

// change return type to Task<int>
public async Task<int> Iobound(SqlConnection conn, SqlTransaction tran) 
{
    // this stored procedure takes a few seconds to complete
    using (SqlCommand cmd = new SqlCommand("MyIoboundStoredProc", conn, tran)) 
    {
        cmd.CommandType = CommandType.StoredProcedure;
        SqlParameter returnValue = cmd.Parameters.Add("ReturnValue", SqlDbType.Int);
        returnValue.Direction = ParameterDirection.ReturnValue;
        // use async IO method and await it
        await cmd.ExecuteNonQueryAsync();
        return (int) returnValue.Value;
    }
}
Sign up to request clarification or add additional context in comments.

10 Comments

@MikeZ Then you usually don't really need to make this method async. Async is for async IO (as you seem to be aware), and all IO has async version nowadays (files, sockets, databases, web requests and so on). If you have counter example - please provide one.
Thanks! But I should have picked a different example. In this case, there is a pre-existing *Async method, ExecuteNonQueryAsync(), assume a different body and no pre-existing *Async method for the I/O-bound call. How would one convert Iobound() to IoboundAsync() without wrapping the synchronous code in Task.Run(), which is not recommended for I/O-bound code?
@MikeZ I've answered above. Please provide an example of such IO that does not have async version. If you mean some another synchronous IO method written by you - you should convert it to async first. So async should go all the way down.
"All IO has async version nowadays" Hmm. I didn't know that. Maybe that's the piece I'm missing.
@MikeZ you need to generate asynchronous client code. Even if WCF service is synchronous on server - client may choose to call it asynchronously (at client side). See here: learn.microsoft.com/en-us/dotnet/framework/wcf/…. So your goal is create/generate Channel.MethodAsync() and of course without any Task.Run
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.