1

I am working on ASP.NET project and yesterday I saw a piece of code that uses System.Threading.Thread to offload some tasks to a new thread. The thread runs a few SQL statements and logs the result.

Isn't it better to use another approach? For example to have a Windows Service that performs the SQL batch. Then the web page will just enqueue the batch (via WCF).

In general, what are the best practices for multithreading in ASP.NET? Are there justified usages of threads/TPL tasks/etc. in a web page?

Nullptr Dev
  • 311
  • 2
  • 10
  • Please explain why you think performing the SQL queries in another process would be better. – Dai Nov 01 '12 at 19:39
  • My main concern is having one more thread for each web request. This effectively doubles the threads and I think it is not a good idea especially when there are many concurrent users. Probably it would be better to write the batch parameters in a table and use SQL Server job to execute the actual queries later. – Nullptr Dev Nov 01 '12 at 22:56

2 Answers2

2

My thought when using multi-threading in ASP.NET:

  1. ASP.NET recycles AppDomain for some reasons like you change web.config or in the period of time to avoid memory leak. The thing is you don't know which exact time of recycle. Long running thread is not suitable because when ASP.NET recycles it will take your thread down accordingly. The right approach of this case is long running task should be running on background process via Queue, like you mention.

  2. For short running and fire and forget task, TPL or async/await are the most appropriate because it does not block thread in thread pool to utilize for HTTP requests.

cuongle
  • 74,024
  • 28
  • 151
  • 206
0

In my opinion this should be solved by raising some kind of flag in the database and a Windows service that periodically checks the flag and starts the job. If the job is too frequent a dedicated queue solution should be used (MSMQ, RabbitMQ, etc.) to avoid overloading the database or the table growing too fast. I don't think communicating directly with the Windows service via WCF or anything else is a good idea because this may result in dropped messages.

That being said sometimes a project needs to run in a shared hosting and cannot setup a dedicated Windows service. In this case a thread is acceptable as a work around that should be removed as soon as the project grows enough to have its own server.

I believe all other threading in ASP.NET is a sign of a problem except for using Tasks to represent async operations or in the extremely rare case when you want to perform a computation in parallel in a web project but your project has very few concurrent users (less concurrent users than the number of cores)

Why Tasks are useful in ASP.NET?

First reason to use Tasks for async operations is that as of .NET 4.5 async APIs return Tasks :) Async operations (not to be confused with parallel computations) may be web service calls, database calls, etc. They may be useful for two things:

  1. Fire several of them at once and your job will take a time equal to the longest operation. If you fire them in sequential (non-async) fashion they will take time equal to the sum of the times of each operation which is obviously more.
  2. They can improve scalability by releasing the thread executing the page - Node.js style. ASP.NET supports this since forever but in version 4.5 it is really easy to use. I'll go as far as claiming that it is easier than Node.js because of async/await. Releasing the thread is important because you may deplete your threads in the pool by having them wait. The result is that your website becomes slow when there are a certain number of users despite the fact that the CPU usage is like 30% simply because new requests are waiting in queue. If you increase the number of threads in the thread pool you pay the price of constant context switching than by the OS. At certain point you will get 100% CPU usage but 40% of it will be spent context switching. You will increase the throughput but with diminishing returns. A lot of threads also increase the memory footprint.
Stilgar
  • 22,354
  • 14
  • 64
  • 101
  • I agree in general. At first I thought about using Windows service though now I think using SQL Server job will be enough. No need for MSMQ, RabbitMQ or whatever. Still I don't see reasons why TPL tasks should be used for async operations. Moreover I don't see a reasonable scenario where async operations on a web server are applicable. Can you elaborate? – Nullptr Dev Nov 01 '12 at 22:50
  • I guess there might be scenarios where TPL tasks are appropriate though I cannot think of any right now. In general, I think there shouldn't be any multithreading on the web server. All available resources (threads) should be used to serve the requests. If you have a lot of concurrent users you will end up with a lot threads. It doesn't matter if there are web requests or I/O completion ports. At some point the server will become overloaded. You can always build the app logic so you can favor short serialized requests instead of (long) parallel tasks. – Nullptr Dev Nov 02 '12 at 09:45
  • Parallelism is only one kind of asynchronous execution. Tasks represent both parallel execution and WAITING. Also it DOES matter if the thread is a worker thread or I/O completion port. The whole point of I/O threads is that they are different from normal threads :) BTW check this related question: http://stackoverflow.com/questions/4842325/use-ajax-or-multithreading-to-speed-up-page-load/4842455 – Stilgar Nov 02 '12 at 11:17