2

I know the differences between a thread and a task., but I cannot understand if creating threads inside tasks is the same as creating only threads.

Javier Silva Ortíz
  • 2,864
  • 1
  • 12
  • 21
GomuGomuNoRocket
  • 771
  • 2
  • 11
  • 37
  • 2
    a task is essentially a promise to do something in the future, threads can help fulfill that promise by spreading a work load across CPUs. – Keith Nicholas Nov 03 '19 at 23:36
  • 1
    I should add, async allows you to efficiently use a single thread for multiple blocking operations so quite often you can use async instead of multiple threads where you don't need to spread a work load, just manage multiple concurrent blocking "tasks" – Keith Nicholas Nov 03 '19 at 23:44
  • Could you provide an example where you are creating a `Thread` inside a `Task`? – Theodor Zoulias Nov 04 '19 at 07:03

3 Answers3

3

It depends on how you use the multithreaded capabilities and the asynchronous programming semantics of the language.

Simple facts first. Assume you have an initial, simple, single-threaded, and near empty application (that just reads a line of input with Console.ReadLine for simplicity sake). If you create a new Thread, then you've created it from within another thread, the main thread. Therefore, creating a thread from within a thread is a perfectly valid operation, and the starting point of any multithreaded application.

Now, a Task is not a thread per se, but it gets executed in one when you do Task.Run which is selected from a .NET managed thread pool. As such, if you create a new thread from within a task, you're essentially creating a thread from within a thread (same as above, no harm done). The caveat here is, that you don't have control of the thread or its lifetime, that is, you can't kill it, suspend it, resume it, etc., because you don't have a handle to that thread. If you want some unit of work done, and you don't care which thread does it, just that's it not the current one, then Task.Run is basically the way to go. With that said, you can always start a new thread from within a task, actually, you can even start a task from within a task, and here is some official documentation on unwrapping nested tasks.

Also, you can await inside a task, and create a new thread inside an async method if you want. However, the usability pattern for async and await is that you use them for I/O bound operations, these are operations that require little CPU time but can take long because they need to wait for something, such as network requests, and disk access. For responsive UI implementations, this technique is often used to prevent blocking of the UI by another operation.

As for being pointless or not, it's a use case scenario. I've faced situations where that could have been the solution, but found that redesigning my program logic so that if I need to use a thread from within a task, then what I do is to have two tasks instead of one task plus the inner thread, gave me a cleaner, and more readable code structure, but that it's just personal flair.

As a final note, here are some links to official documentation and another post regarding multithreaded programming in C#:

Javier Silva Ortíz
  • 2,864
  • 1
  • 12
  • 21
2

It depends how you use tasks and what your reason is for wanting another thread.

Task.Run

If you use Task.Run, the work will "run on the ThreadPool". It will be done on a different thread than the one you call it from. This is useful in a desktop application where you have a long-running processor-intensive operation that you just need to get off the UI thread.

The difference is that you don't have a handle to the thread, so you can't control that thread in any way (suspend, resume, kill, reuse, etc.). Essentially, you use Task.Run when you don't care which thread the work happens on, as long as it's not the current one.

So if you use Task.Run to start a task, there's nothing stopping you from starting a new thread within, if you know why you're doing it. You could pass the thread handle between tasks if you specifically want to reuse it for a specific purpose.

Async methods

Methods that use async and await are used for operations that use very little processing time, but have I/O operations - operations that require waiting. For example, network requests, read/writing local storage, etc. Using async and await means that the thread is free to do other things while you wait for a response. The benefits depend on the type of application:

  • Desktop app: The UI thread will be free to respond to user input while you wait for a response. I'm sure you've seen some programs that totally freeze while waiting for a response from something. This is what asynchronous programming helps you avoid.

  • Web app: The current thread will be freed up to do any other work required. This can include serving other incoming requests. The result is that your application can handle a bigger load than it could if you didn't use async and await.

There is nothing stopping you from starting a thread inside an async method too. You might want to move some processor-intensive work to another thread. But in that case you could use Task.Run too. So it all depends on why you want another thread.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
-5

It would be pointless in most cases of everyday programming.

There are situations where you would create threads.

tymtam
  • 31,798
  • 8
  • 86
  • 126