1

So here I have a function

static bool Login(SignupData sd)
{
   bool success=false;
   /*
      Perform login-related actions here
   */
}

And there is another function

static Task<bool> LoginAsync(SignupData sd)
{
   return Task.Run<bool>(()=>Login(sd));
}

Now, I've come across a rather different implementation of this pattern, where you would add the async keyword to a function which returns Task<TResult> (so that it ends up looking like: async Task<TResult> LoginAsync(SignupData sd)). In this case, even if you return TResult instead of a Task<TResult>, the program still compiles.

My question here is, which implementation should be prefered?

static Task<bool> LoginAsync(SignupData sd)
{
   return Task.Run<bool>(()=>Login(sd));
}

OR this one?

async static Task<bool> LoginAsync(SignupData sd)
{
    bool success=Login(sd);
    return success;
}
7
  • 1
    move your question to code review stack exchange Commented Mar 14, 2016 at 17:42
  • @KevinAvignon Please check the Code Review rules before suggesting to post questions there. Commented Mar 14, 2016 at 17:43
  • 2
    You should be getting compiler warning for the second method. And none of the implementations is good. If you can't provide truly async method, then just don't provide it. The caller can always do Task.Run. Commented Mar 14, 2016 at 17:44
  • @KevinAvignon This is not an acceptable question for Code Review, as it contains stub code or a small portion of a piece of code. Please see A guide to Code Review for Stack Overflow users before recommending Code Review. Commented Mar 14, 2016 at 17:45
  • 1
    The second one really should be return await Task.Run<bool>(()=>Login(sd));. At the very least you should have an await in a method marked with async. Commented Mar 14, 2016 at 17:46

2 Answers 2

7

You shouldn't be doing either. Asynchronous methods are useful if they can prevent threads from being blocked. In your case, your method doesn't avoid that, it always blocks a thread.

How to handle long blocking calls depends on the application. For UI applications, you want to use Task.Run to make sure you don't block the UI thread. For e.g. web applications, you don't want to use Task.Run, you want to just use the thread you've got already to prevent two threads from being used where one suffices.

Your asynchronous method cannot reliably know what works best for the caller, so shouldn't indicate through its API that it knows best. You should just have your synchronous method and let the caller decide.


That said, I would recommend looking for a way to create a LoginAsync implementation that's really asynchronous. If it loads data from a database, for instance, open the connection using OpenAsync, retrieve data using ExecuteReaderAsync. If it connects to a web service, connect using the asynchronous methods for whatever protocol you're using. If it logs in some other way, do whatever you need to make that asynchronous.

If you're taking that approach, the async and await keywords make perfect sense and can make such an implementation very easy to create.

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

8 Comments

How is this an argument against async (or tasks, ignoring the choice of Run) as a composition?
@user2864740 Either I don't understand your question, or I don't see how it relates to my answer. Can you elaborate?
Is IHttpClient { Task<HttpResponseMessage> GetAsync(Uri path); } a valid interface?
+1 from me. I think it's the first time I see someone advocating for using Task.Run on UI apps. I've been criticised in the past (not in Stack Overflow) for saying the same :-)
@user2864740 yes it is, and you can make your implementation using async or not (depending on if you use await or other means of creating a Task), and you let your caller call your GetAsync method using await or not, as they choose
|
0

While HVD is correct, I will dive into async in an attempt to describe its intended use.

The async keyword, and the accompanying await keyword is a shortcut method of implementing non blocking code patterns within your application. While it plays along perfectly with the rest of the Task Parallel Library (TPL), it isn't usually used quite the same. It's beauty is in the elegance of how the compiler weaves in the asynchronicity, and allows it to be handled without explicitly spinning off separate threads, which may or may not be what you want.

For Example, let's look at some code:

async static Task<bool> DoStuffAsync()
{
    var otherAsyncResult = doOtherStuffAsync();

    return await otherAsyncResult
}

See the await keyword? It says, return to the caller, continue on until we have the result you need. Don't block, don't use a new thread, but basically return with a promise of a result when ready (A Task). The calling code can then carry on and not worry about the result until later when we have it.

Usually this ends up requiring that your code becomes non-blocking the whole way down (async all the way as it were), and often this is a difficult transition to understand. However, if you can it is incredibly powerful.

The better way to handle your code would be to make the synchronous code call the async one, and wait on it. That way you would be async as much as possible. It is always best to force that level as high as possible in your application, all the way to the UI if possible.

Hope that made sense. The TPL is a huge topic, and Async/Await really adds some interesting ways of structuring your code. https://msdn.microsoft.com/en-us/library/hh191443.aspx

Comments

Your Answer

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