14

If I have a normal method that I want to make asynchronous:

public int Foo(){}

I would do:

public Task<int> FooAsync(){
    return Task.Run(() => Foo());
}

Why would I do:

public async Task<int> FooAsync(){
    return await Task.Run(() => Foo());
}

The way I plan to use this is:

FooAsync().ContinueWith((res) => {});

I want the method to just run without stopping, but I want something like a callback to be fired, hence the ContinueWith. But with the second version, is there a point to using it?

Shawn Mclean
  • 56,733
  • 95
  • 279
  • 406

2 Answers2

13

In my understanding, you only need async and await when you write a method which does some async calls inside, but you would like it to look like it doesn't. In other words you want to write and read code as if it was some normal sequential code, handle exceptions as if it was normal sequential code, return values as if it was normal sequential code and so on. Then compiler's responsibility is to rewrite that code with all the necessary callbacks preserving the logic.

Your method is so simple I don't think it needs that rewriting at all, you can just return the task, but whoever consumes it may want to await for its return value.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Massimiliano
  • 16,770
  • 10
  • 69
  • 112
  • Thank you, @paulsm4. I must say that I'm just retelling what I've recently heard, I think, it's from the http://hanselminutes.com/327/everything-net-programmers-know-about-asynchronous-programming-is-wrong, but not 100% sure. I didn't have much experience with the async feature yet, so I might be wrong and I'd be happy to learn more, maybe async provides some benefits in this case. – Massimiliano Sep 03 '12 at 07:46
  • 2
    In addition, you may want to read [Should I expose asynchronous wrappers for synchronous methods?](http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx) (The answer almost always is "no;" if you have a synchronous method, then give it a synchronous method signature). – Stephen Cleary Sep 04 '12 at 05:19
  • Without a single mention of IO, this answer falls way short of a complete answer. – spender Sep 23 '12 at 22:00
  • @Yacoder is right about the uses of async and await. [Here is a good example of when to use it](http://tech.pro/tutorial/1180/asynchronous-programming-in-c-using-async-and-await) – strangeloops Apr 08 '13 at 16:48
5

Why would I do:

 public async Task<int> FooAsync()
 {
  return await Task.Run(() => Foo());
 }

You wouldn't. Your previous version returns Task which is already awaitable. This new version doesn't add anything.

The way I plan to use this is:

  FooAsync().ContinueWith((res) => {});

I want the method to just run without stopping, but I want something like a callback to be fired, hence the ContinueWith.

This is where the difference comes in. Let's flesh out your example a little bit:

void DoAsyncStuff()
{
    FooAsync().ContinueWith((res) => { DoSomethingWithInt(res.Result) });
}

Using async, you can write the same code like this:

void async DoAsyncStuff()
{
    int res = await FooAsync();
    DoSomethingWithInt(res);
}

The result is the same. The await keyword turns the rest of your method into a continuation which gets resumed after FooAsync produces a value. It's just like your other code, but easier to read. *shrug*

Mud
  • 28,277
  • 11
  • 59
  • 92
  • Your `async` method really shouldn't be void returning. `async` methods should only be void returning when they will be a handler for an event. It should return `Task` if there is no return value in the method. Other than that, decent enough post. – Servy Feb 19 '13 at 18:35
  • @Servy "async methods should only be void returning when they will be a handler for an event." That's the case here, right? What should `DoAsyncStuff` return in this example, and where would it get that value without writing superfluous code? Also, if an async method returns Task and you *don't* await it, you get a compiler warning (CS4014), which is annoying. I recently [asked about that issue](http://stackoverflow.com/questions/14903887/warning-this-call-is-not-awaited-execution-of-the-current-method-continues) here. If you have a better answer, could you post it there? – Mud Feb 19 '13 at 19:57
  • When an `async` method returns void it essentially makes it a "fire and forget" method. The caller has no way of knowing when the method actually finishes. There is no indication from the OP's code here that that's what he wants. As for the compiler warning, that's because you almost certainly *don't want to be doing that*, as I told you in the post you linked to; the warning is *correctly* indicating that there is a flaw in your design, and that odds are you don't want the behavior you're getting. While you may want that behavior in a few edge cases, I stand by my assertions. – Servy Feb 19 '13 at 20:04
  • **"no way of knowing when the method actually finishes."** When FooAsync returns, it either (1) invokes a callback as in the OP's example, or (2) resumes a compiler created callback via the `await` keyword. Either way, the code that needs to know about it is invoked. **"no indication from the OP's code that that's what he wants."** He said that's what he wants: "I want something like a callback to be fired". **"don't want to be doing that"** Doing what? Like I said before, I asked about this on Stackoverflow. If you have a better answer, could you articulate it there, so you have more room? – Mud Feb 19 '13 at 21:47
  • 1) The method that calls `DoAsyncStuff` will have no way of knowing when `DoSomethingWithInt` has finished running. That's what I mean by the statement you quoted. If the caller wants to execute a continuation that runs after your continuation, he can't, unless the method returns a `Task`. 2) That wasn't what I was referring to. I said that an `async` method should only return `void` if it's an event handler, you said, `"That's the case here, right?"` There's no indication that's true. 3) Again, that's not what I was referring to. The OP almost certainly doesn't want to fire and forget. – Servy Feb 19 '13 at 21:58
  • **"method that calls DoAsyncStuff will have no way of knowing when DoSomethingWithInt has finished"** Handling is contained within the method, as in the OP's example. **"OP almost certainly doesn't want to fire and forget."** His example puts the code that needs to be notified of the response in a closure. `async` lets him move that out of the closure (into a compiler generated one). At some point up the stack, there's always going to be a non-async method which cannot `await` and is not returning Task, right? If I'm wrong, can you PLEASE articulate what you mean in the post I mentioned? – Mud Feb 19 '13 at 22:14