2

I'm trying to understand tasks in .net from what I understand is that they are better than threads because they represent work that needs to get done and when there is a idle thread it just gets picked up and worked on allowing the full cpu to be utilized.

I see the Task<ActionResult> all over a new mvc 5 project and I would like to know why this is happening?

Does it make sense to always do this, or just when there can be blocking work in the function?

I'm guessing since this does act like a thread there is still sync objects that may be needed is this correct?

tereško
  • 58,060
  • 25
  • 98
  • 150
dbarnes
  • 1,803
  • 3
  • 17
  • 31

2 Answers2

5

MVC 5 uses Task<ActionResult> to allow it to be fully asynchronous. By using Task<T>, the methods can be implemented using the new async and await language features, which allows you to compose asynchronous IO functions with MVC in a simple manner.

When working with MVC, in general, the Task<T> will hopefully not be using threads - they'll be composing asynchronous operations (typically IO bound work). Using threads on a server, in general, will reduce your overall scalability.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
3

A Task does not represent a thread, even logically. It's not just an alternate implementation of threads. It's a higher level concept. A Task is the representation of an asynchronous operation that will complete at some point (usually in the future).

That task could represent code being run on another thread, it could represent some asynchronous IO operation that relies on OS interrupts to (indirectly, through a few other layers of indirection) cause the task to be marked completed), it could be the result of two other tasks being completed, or the continuation of some other task being completed, it could be an indication of when an event next fires, or some custom TaskCompletionSource that has who knows what as its implementation.

But you don't need to worry about all of those options. That's the point. In other models you need to treat all of those different types of asynchronous operations differently, complicating your asynchronous programs. The use of Task allows you to write code that can easily be composed with any and every type of asynchronous operation.

I'm guessing since this does act like a thread there is still sync objects that may be needed is this correct?

Technically, yes. There are times where you may need to use these, but largely, no. Ideally, if you're using idiomatic practices, you can avoid this, at least in most cases. Generally when one task depends on code running in other tasks it should be the continuation of that task, and information is assessed between tasks through the tasks' Result property. The use of Result doesn't require any synchronization mechanisms, so usually you can avoid them entirely.

I see the Task all over a new mvc 5 project and I would like to know why this is happening?

When you're going to make something asynchronous it generally makes sense to make everything asynchronous (or nothing). Mixing and matching just...doesn't work. Asynchronous code relies on having every method take very little time to execute so that the message pump can get back to processing its queue of pending tasks/continuations. Mixing asynchronous code and synchronous code makes it very likely to deadlock your application, and also defeats most of the purposes of using asynchrony to begin with (which is to avoid blocking threads).

Servy
  • 202,030
  • 26
  • 332
  • 449
  • So does this mean every action Method and webAPI method should always have Task, or only when you expect it to do some kind of asynchronous operation? – dbarnes Dec 18 '13 at 21:17
  • @dbarnes So generally you're going to be writing very few operations that are defining something asynchronous. What you're generally doing is writing a bunch of operations that are dependent on other asynchronous operations. If your method is calling some library method that asynchronously queries a database, then that method should be asynchronous, which means it should return a `Task`, and any method that uses that method needs to be asynchronous, and all the way up to the top level MVC method that returns a task. If a method isn't dependent on any asynchronous operation, it need not do so. – Servy Dec 18 '13 at 21:23
  • Ok I think I understand now, so say for instance if I had a function that read some data say UserName and Password from a DB I would want that function to Return Task all the way up to the method that validates the username/Password? – dbarnes Dec 18 '13 at 21:26
  • Then await comes into play when you decide that the task no long needs to be asynchronous allowing the initial function to be halted? – dbarnes Dec 18 '13 at 21:28
  • @dbarnes No, `await` is simply a clever way of writing a function that looks as if it is synchronous, but which is transformed by the compiler into code that really is asynchronous, which is what makes it such a powerful feature. You could perform the transformation yourself, but it is a lot of boilerplate code to do so, and code that isn't particularly pleasant to work with. – Servy Dec 18 '13 at 21:50