I've got a few instances of the same class. During the classes lifetime, every method call on this class should be executed on the same thread. But for each instance I need a different thread.
I thought about Threadpool, but it seems that I have too less control about it.
How can I reuse a thread without using ThredPool?
Thank you! Martin
Edit (why I need this):
I have to use a win32 dll to access business logic of a third-party product. This dll is not designed for a multi-threaded environment like a web application. When I run my ASP.NET MVC application in ASP Classic Mode (STA Thread), everything works fine so far. But the problem is that all users going to block each other. This component also maintains some state. As soon as a different thread is accessing this component, it will not recognize the connection-handle I have to pass in for each method call. I got the connection handle after a logon procedure. I want to put my web application in MTA mode back again and use a worker-concept, assigning about 10 users to a worker (max. 10 users should block each other). One worker should always use the same thread to execute the api calls so the component will not stubmle.
I'm not happy with this situation, but I have to find am acceptable solution.
Update - Found a Solution:
Thanks to the "Smart Thread Pool" from Ami Bar I could accomplish the behavior I was looking for (easily). For each worker, I have now my own thread pool instance with a max and min number of one thread. Well, it's not the idea of a thread pool, but it makes it very easy to handle the work-items and it also has some nice other featrues. The web application is running on MTA now.
I'm going to prepare some load tests to see if its stable over hours.
see here: http://www.codeproject.com/Articles/7933/Smart-Thread-Pool
Related
Background: I have a simple ASP.NET Core 3.1 site. Very rarely (three or four times per week), a user might fill out a form that triggers an email to be sent.
I don't want to delay the page response while running the 'send email' operation (even though it only takes a second or two), so from everything I've read, it seems like the code that should handle the email should be a background worker/hosted service, and the Razor pages code should place the data object to be sent in a collection that gets monitored by the background service.
What I'm not fully understanding is why this is necessary in modern ASP.NET Core.
If I was doing this in a normal C# application (not ASP), I'd simply make the 'send email' method async (it's using MailKit, which has async methods), and call the async method without awaiting, allowing the the work be done on the threadpool while allowing the response thread to continue.
But existing answers and blog posts say that calling an async method without an await in ASP is dangerous, due to the fact that IIS can restart ASP processes (application pool recycling).
Yet, most things I've read say Application Recycling is an artifact of old ASP when memory leaks were common, and it's not really a thing on .Net Core. Additionally, many ASP applications aren't even hosted in IIS anymore.
Further, as far as I can tell, IHostedService/Background Worker objects aren't doing anything special - they don't seem to add any additional threading; they just look like singletons that have additional notification for environment startup and shutdown.
So:
Is calling a fire-and-forget async method in ASP.NET Core still considered poor practice, especially if the fire and forget task is short-lived? If so, why? [see edit below for clarification]
Other than notifications for shutdown, is there any reason why a background service is considered better than borrowing a managed threadpool thread (via Task.Run or QueueBackgroundWorkItem)? Wouldn't waking a background service (if it was awaiting on object to be placed in a collection) consume a pool thread in the same way?
Edit: I acknowledge that starting a task, and reporting success to the user, when there's a chance that operation could be terminated, is poor form. There's benefit to being notified of a shutdown and being able to finalize tasks.
Perhaps a better question is, does the old behavior of cycling still exist in modern ASP (on IIS or Kestrel)? Are there other reasons an orderly shutdown might be triggered (other than server shutdown/manual stop)?
I would still call it a poor practice.
The main concern here as well as in the referenced post is mainly about the promise of task completion.
Without being aware of the ghost background tasks, the runtime will not be able to notify the tasks to gracefully stop. This may or may not cause serious issues depending on the status of the tasks at the point the termination occurs.
Using fire forget task often means, your task is at the risk of having to start all over again when the process restarts. And sometimes this is not possible due to loss of context. Imagine your fire-forget task is calling another web API with parameters provided by a web request. The parameters are likely to get wiped out from memory if the process restarts.
And remember, the recycling is not always triggered by IIS / server. It could also be triggered by people. Say when your application runs into a memory leak issue, and you may want to recycle the app process every 1 hour as a temporary relief. Then you need to make sure you don't break your background tasks.
In terms of hosting - it is still possible to host ASP.Net Core applications in-process, in which the app pool gets recycled by IIS after a configured time period, or by default 29 hours.
In terms of lifetime - hosted services are types you register to DI, so DI features could be used, for example, this built-in hosted service implements IDisposable, which means proper clean up could be done upon shutting down.
Frankly, background tasks and hosted services both allow you to do fire and forget. But when you need reliability and resilience, hosted services win.
To answer the second half of your question, the app will wait for all hosted services' StopAsync methods to finish before shutting down. As long as you await your Tasks in the hosted service, this effectively means you can assume your Tasks will be allowed to finish running before the app shuts down. The app could still be force-shutdown, which in that case, nothing is guaranteed anymore.
If you need more guarantees about your background tasks, you should move them to run in a separate process. You could use something like Runly to make it easier to break out functionality into background jobs. It also makes it easy to provide real-time feedback to the user so that you are not lying to the user when you say "everything is done" while something is still running in the background.
Full disclosure: I cofounded Runly.
I'm after a bit of advice concerning multi threading / web services, and if / how I should use one of these for my issue.
I have a button on my c# asp site that does a bunch of api calls, and the process can take several minutes.
I want to split this process off, so that it can perform 'in the background' and will not upset the user experience.
The process is tighly wound into my current project, so it isn't easy to split code off into a separate web service project.
So..
If I run the following Thread code, will it perform successfully if the user kills the browser? What are my issues/considerations?
Thread thread = new Thread(new ThreadStart(RefreshData));
If the above doesnt work, can I make this work by adding some [web methods] to the same project, and call them from the same project? (if so - any tips?)
If I do this will it successfully perform them in another iis thread? ie.. if the users kills their browser - can I be sure that the processes from the service will complete successfully?
Also, I'm planning to host the site on AWS - so if there are considerations from that perspective any insights would also be helpful.
Thanks in advance gang..
You can run background threads. They run even if the visitor closed the browser window. You can associate these threads/workload with the visitor using sessions/cookies, so even after they re-visit the website they can pick up with the progress.
What you have to pay attention is to keep the web server process from recycling. That would occur after a certain timeout or lifetime by default. You must change relevant settings.
Also, keep a permanent reference to the thread you created to prevent it garbage collected.
I am looking to write a Windows Service that will start various "jobs".
Each "job" will:
be distinct in what it accomplishes
run for the lifetime of the Service, so "long running". Typically, a job will get 10 tasks from the database and process them, then sleep, and then repeat this cycle again and again.
Share the same "context". The application will be loosely coupled and call an IoC to get classes. It will also store some data on this context too
I need each job to be able to run in parallel and effectively run as separate programs.
My first thought was to create one thread per job. This is okay but has the drawback that a ManualResetEvent stops the thread in its tracks, and the Abort doesn't allow much chance for the Thread to exit in a graceful manner.
I then explored some of the new async framework in .NET 4.5 and boy does it seem to simplify coding.
However, whilst some of the data held on the context may be freely shared between each job, some can not: so each job requires it's own copy of certain data.
I attempted to solve this using ThreadLocal<T> properties. However, whilst this works fine for a specific thread that I've created, this doesn't work for the async methods. The thread that starts an async method is often not the thread that finishes the method, particularly when the method uses "await".
So, what is the preferred pattern for what I am attempting to accomplish?
FYI: Albahari's posting was a great help.
I'm working on creating an async handler for ASP.NET that will execute a slow stored procedure. I think I understand that to gain additional throughput on a mixed load of slow and fast pages, the slow page needs to be executed on a thread pool separate from the one the ASP.NET uses, otherwise the async pattern will cause double the number of scarce threads to be used (correct me if I'm wrong).
So I have found System.Threading.ThreadPool - it looks like it should do the trick, but...
The various tutorials on the net such as this one which uses this custom pool, the one in John Skeet's MiscUtils, and the custom thread pool referenced in this tutorial about async patterns.
System.Threading.ThreadPool has existed since 1.1 - why do people routinely feel the need to write a brand new one? Should I avoid using System.Threading.ThreadPool?
I'm a rank beginner when it comes to threading, so go easy on the undefined jargon.
UPDATE. The stored procedure to be executed will not necessarily be MS-SQL and will not necessarily be able to use a built-in async method such as BeginExecuteNonQuery().
Here's what I found on the topic. Why you shouldn't use ThreadPool in ASP.NET http://madskristensen.net/post/Done28099t-use-the-ThreadPool-in-ASPNET.aspx. It's quite old but I don't think it has changed that much. Or correct me if I'm wrong.
Using the System.Threading.ThreadPool or a custom delegate and calling its BeginInvoke offer a quick way to fire off worker threads for your application. But unfortunately, they hurt the overall performance of your application since they consume threads from the same pool used by ASP.NET to handle HTTP requests.
Using custom threads with the aid of System.Threading.Thread class should solve the problem as the threads created are not part of your application's pool.
I’m looking for the best way of using threads considering scalability and performance.
In my site I have two scenarios that need threading:
UI trigger: for example the user clicks a button, the server should read data from the DB and send some emails. Those actions take time and I don’t want the user request getting delayed. This scenario happens very frequently.
Background service: when the app starts it trigger a thread that run every 10 min, read from the DB and send emails.
The solutions I found:
A. Use thread pool - BeginInvoke:
This is what I use today for both scenarios.
It works fine, but it uses the same threads that serve the pages, so I think I may run into scalability issues, can this become a problem?
B. No use of the pool – ThreadStart:
I know starting a new thread takes more resources then using a thread pool.
Can this approach work better for my scenarios?
What is the best way to reuse the opened threads?
C. Custom thread pool:
Because my scenarios occurs frequently maybe the best way is to start a new thread pool?
Thanks.
I would personally put this into a different service. Make your UI action write to the database, and have a separate service which either polls the database or reacts to a trigger, and sends the emails at that point.
By separating it into a different service, you don't need to worry about AppDomain recycling etc - and you can put it on an entire different server if and when you want to. I think it'll give you a more flexible solution.
I do this kind of thing by calling a webservice, which then calls a method using a delegate asynchronously. The original webservice call returns a Guid to allow tracking of the processing.
For the first scenario use ASP.NET Asynchronous Pages. Async Pages are very good choice when it comes to scalability, because during async execution HTTP request thread is released and can be re-used.
I agree with Jon Skeet, that for second scenario you should use separate service - windows service is a good choice here.
Out of your three solutions, don't use BeginInvoke. As you said, it will have a negative impact on scalability.
Between the other two, if the tasks are truly background and the user isn't waiting for a response, then a single, permanent thread should do the job. A thread pool makes more sense when you have multiple tasks that should be executing in parallel.
However, keep in mind that web servers sometimes crash, AppPools recycle, etc. So if any of the queued work needs to be reliably executed, then moving it out of process is a probably a better idea (such as into a Windows Service). One way of doing that, which preserves the order of requests and maintains persistence, is to use Service Broker. You write the request to a Service Broker queue from your web tier (with an async request), and then read those messages from a service running on the same machine or a different one. You can also scale nicely that way by simply adding more instances of the service (or more threads in it).
In case it helps, I walk through using both a background thread and Service Broker in detail in my book, including code examples: Ultra-Fast ASP.NET.