Multithreading with a task library

in ASP.NET MVC I have an activity that takes a list of email addresses entered by the user, validates them, and then sends the HTML and text version of the email message to each recipient. The user is then redirected to a thank you page. Since there is no need to wait to be redirected to the thank you page until all emails have been sent, I use the Task.Factory.StartNew method to start a new task that actually sends emails, and it works fine; the user is immediately redirected to the thank you page and the emails are sent in a separate thread. So, everything works the way I want, but nonetheless I have the following questions regarding multithreading. I've read quite a few posts in the past days,but I still don't have the answers, here are some facts that I extracted from these posts (note that these are just my assumptions and I am writing them down here so you can comment and improve them):

  • The task library uses a thread from a thread pool

    If you are using the Task Library, you create a new thread using a thread from the ASP.NET thread pool. This means that one thread is less available to serve other ASP.NET requests for the application. So, by using the task library, you are not optimizing your use of ASP.NET threads by offloading tasks to some other OS thread, only the UI works better, but the task library uses a different thread that can be used to serve other ASP.NET requests ... Therefore, the only consequence is that the user does not have to wait.

  • Hand thread

    If you really want to use OS threads, you must explicitly start a new thread. But even if you are starting a new thread of OS, you need to have a machine with multiple cores or processors to really see the scalability improvement of applications.

  • Shared thread pool

    Some of the posts talk about the ASP.NET thread pool and a separate application thread pool that is used for background tasks. In other words, each ASP.NET application has one thread pool to serve application requests and another thread pool to perform background tasks. I don't think this is true, I think every ASP.NET application only has one thread pool and threads from that pool are used for the server: application requests and background tasks. Perhaps this could be said for a Windows Forms application where normally only one thread (UI thread) runs and you have to explicitly start a new thread. But ASP.NET is multithreaded in its core principles.

Here are the questions:

  • I have read about async MVC controllers in ASP.NET MVC 2 programming from Dino Esposito. He writes about how an async controller uses an OS thread for a long running task, and thus the ASP.NET thread that originally made an ASP.NET request can now freely request other server requests.

    Although I don't need an async controller here, my questions are: How can I use such an OS thread in my example. Do I have to start a separate thread explicitly or is this also possible using the task library?

  • Even if I offload such tice to some OS thread, would it be of any use if there was only one processor on the machine? I think a multi-core machine is needed to really improve the scalability of an application.

+3


source to share


2 answers


[...] He writes about how an async controller uses an OS thread for a long running task, and thus the ASP.NET thread that originally made the ASP.NET request can now freely send other server requests.

Well it depends on what kind of code you have in that async controller. It can execute some code on the OS Thread

, but it doesn't have to. What usually happens is that you start some async operation that doesn't use threads at runtime. And when it ends, the result is fed back to the stream ThreadPool

.

Although I don't need an async controller here, my questions are: How can I use such an OS thread in my example. Do I have to start a separate thread explicitly or is this also possible using the task library?

You can start a new thread using TaskCreationOptions.LongRunning

. This does not guarantee the start of a new stream, but in practice it does.

Even if I unload such tice into some OS thread, will there be any benefit if there is only one processor on the machine? I think a multi-core machine is needed to really improve the scalability of an application.

It can be useful if this thread is performing some I / O bind operation synchronously. For example, most of the time spent sending email is likely not wasting CPU usage, but waiting for the server to respond. If this case, using a different thread (no matter if a separate thread or one of them ThreadPool

) might be helpful. Of course, it would be even better if you perform this operation asynchronously, which will not block any thread, but this can make your code a lot more complicated (and there may be times when this is not even possible).



Regarding other things you wrote:

If you are using the Task Library, you create a new thread using a thread from the ASP.NET thread pool. This means that one thread is less available to serve other ASP.NET requests for the application.

Yes, under normal circumstances (if you use the default TaskScheduler

and don't specify TaskCreationOptions.LongRunning

). But if you're having trouble with this, the best solution might be to increase the ThreadPool limits rather than building Thread

yourself for short tasks. This is because creating and destroying threads is an expensive operation and you should avoid it if performance is important to you.

[E] An ASP.NET application has one thread pool for serving application requests and another thread pool for performing background tasks. I don't think this is true, I think that every ASP.NET application has only one thread pool, and threads from this pool are used for the server both: application requests and background tasks.

This is a little more complicated, but yes, ASP.NET requests and ThreadPool tasks (started with ThreadPool.QueueUserWorkItem()

or by running Task

with default parameters) run in the same thread pool.

+1


source


The real problem is that ASP.NET can recycle your AppDomain at any time. When this happens, your background thread will be interrupted with extreme prejudice. It doesn't matter if you are using a thread stream or starting your own thread - if ASP.NET doesn't know about this thread, it can both destroy the AppDomain and take your thread with it.

The "correct" solution is to have a separate Windows service process that is the WCF server. Then your web application can send commands to the service that executes them - for example. sends multiple emails.



The quick and dirty way is to have a hidden action in your web app that sends emails. Run an asynchronous request for this action and then return a thank you page without waiting for the result. ASP.NET doesn't care about the request coming from your application - it just treats it like another request. Because ASP.NET "knows" about the request, it does not cancel it.

+4


source







All Articles