How to optionally run some code on a background thread? - asp.net

I'm looking for a configurable way to run some code on a background thread and I'm not too sure what the "best practice" would be. Currently I have something along the lines of:
Dim sendEmails = Sub()
Dim emailToSend As New SendEmailRequest()
TransferCommonValuesTo(emailToSend, request, sendingUser)
usersToSendEmailTo.ForEach(Sub(u)
TransferValuesTo(emailToSend, u, m_EmailMessageMerger.GetMergedMessage(request.Message, u))
m_EmailSender.Send(emailToSend)
End Sub)
End Sub
If cfg.SendBulkEmailUsingBackgroundThread Then
Dim worker As New Thread(sendEmails)
worker.IsBackground = True
worker.Start()
Else
sendEmails()
End If
Is this a good way of implementing my requirement?
Update:
This will be called from an ASP.NET front-end (although others are possible) and I am using Framework 3.5.

I would tend to abstract this behaviour away in its own class say TaskRunner, and have a Run method which accepts an Action. This separates threading concerns and makes your code neater, you also have more flexibility on how you implement your asynchronous behaviour without having this embedded in various classes in your application.
If you do have asynchronous actions running in a Asp.Net app, you will need to look at a mechanism to keep the application alive to prevent application recycling e.g. by polling a page in your site whilst the action is running to maintain active requests so the runtime doesn't think it's idle.

I suspect most people would tend to use the BackgroundWorker class instead.
Of course you could also look at using Task(of T) in .NET 4.0 as well.

This is almost always a bad idea !!. For example, consider a case where you have the default settings in IIS. IIS shuts down the app pool, if it is idle (i.e. doesn't receive any requests) for 20 minutes. In such cases, if your background job runs for more than 20 minutes, it will fail. There are several other reasons for IIS to shut down the app pool. The app domain could recycle if someone changes web.config, thus causing failure of the job. Overall, it is not good for the stability of your web application.
The correct way to do this is using a windows services or some other scheduling component (may be a job in your database server).
There are several open source options available. For e.g. Quartz.net

Related

ASP.Net C# 4.0 - How to catch application thread exceptions

I have an ASP.Net website that has custom internal threads, for periodically occurring tasks.
If I get an exception on one of these threads, it is not caught in Global.ASAX's Application_Error() function. It is allowed to bubble up to IIS and I find out about it by reviewing the Event Viewer logs. If I catch the exception then Log4Net will direct an email to me and I should find out about the error relatively quickly.
Is there a way I can trap exceptions on these threads? The app needs to be 'always-on', so an exception that drops the application is a show-stopper.
In a comment you mentioned:
This is a web-site rather than web app.
"Web site" vs. "web app" seems like a moot distinction at this point. There's enough complexity in the code that it's an "application" by pretty much any definition of the word. To that point, if the application host doesn't meaningfully manage thread faults for you (and I wouldn't expect a web application host to do so) then you have to manage them manually.
In this case I see that as one of two options:
Option 1: Don't let your threads end in a faulted state. Whatever your top-level worker item for any given thread is (a method invoked at the start of the thread, a loop repeating operations, etc.), that needs to be essentially fault-proof. No exception should get past that. Which means it needs to be dead simple (so as to not throw exceptions of its own) and needs to catch any and all exceptions from the operation(s) it invokes.
Once caught, do with them as you please. Roll back a unit of work, notify someone of the error, etc.
Option 2: Move the long-running thread operations out of the web application, since web applications aren't really suited for ongoing background processes. A Windows Service or scheduled Console Application is a much more suited application host for that logic.
Yes, bit of a re-write there though.
Is it? It shouldn't be. That's really a matter of how the code was originally architected, not related to the application hosts themselves. Invoking a business operation from one application host is the same as invoking it from another. If the logic is tightly coupled to the application technology, that's a separate problem. And there's no quick fix to that problem. The good news is that once you fix that problem, other problems (like the one which prompted this question) are quick fixes.

How many instances of a web application are running in one worker process?

I have a single ASP.NET MVC 4 web application (MvcApplication which extends System.Web.HttpApplication) hosted on IIS 8. My application is running on a separate application pool in integrated pipeline mode. Maximum worker process count for this application pool is set to 1.
I understand, that application instances might get pooled and there might be multiple parallel threads, which will call Begin_Request/End_Request for the same instance of my application (AppDomain). Also I understand that if I set "Maximum worker process count" to more than 1 then there will definitely more than one instance of the application (AppDomain).
What I don't understand is how many calls to Application_Start will be issued and how many instances of my static variables (stored in MvcApplication and also there are some singletons, like NHibernate session factory etc.) will exist at a given moment.
Currently I have some problems with cleaning up .NET MemoryCache. Some users of my website are receiving old values from the cache, thus leading me to think that there might exist more than one instance of my global MemoryCache, even when I set "Maximum worker process count" to 1.
What is the maximal number of instances of my application static variables and singletons which will be run in parallel in a single worker process?
Is there any utility or script which would help me to enumerate all AppDomains on IIS?
I'm not sure if this applies to you, but HttpModule Initialize methods are called more than once because even though there is only one Application instance. One HttpApplication can spawn multiple HttpModule instances, so make sure those initializations are thread safe.
Application_Start and _End will fire only once per site start and stop with your current settings, so that will not be the issue. If you are using the HttpContext.Cache object, you might have the issue mentioned in this answer:
HashTable in HttpContext.Current.Cache
If you want, you can try using WinDbg and get a dump of what is going on in your process but that is a really heavy-handed tactic that probably won't shed as much light as just looking through the code. Not until you look at it a little harder, and are still stumped IMO.

Correctly implement background process Thread in ASP.NET

I need to execute an infinite while loop and want to initiate the execution in global.asax.
My question is how exactly should I do it? Should I start a new Thread or should I use Async and Task or anything else? Inside the while loop I need to do await TaskEx.Delay(5000);
How do I do this so it will not block any other processes and will not create memory leaks?
I use VS10,AsyncCTP3,MVC4
EDIT:
public void SignalRConnectionRecovery()
{
while (true)
{
Clients.SetConnectionTimeStamp(DateTime.UtcNow.ToString());
await TaskEx.Delay(5000);
}
}
All I need to do is to run this as a singleton instance globally as long as application is available.
EDIT:SOLVED
This is the final solution in Global.asax
protected void Application_Start()
{
Thread signalRConnectionRecovery = new Thread(SignalRConnectionRecovery);
signalRConnectionRecovery.IsBackground = true;
signalRConnectionRecovery.Start();
Application["SignalRConnectionRecovery"] = signalRConnectionRecovery;
}
protected void Application_End()
{
try
{
Thread signalRConnectionRecovery = (Thread)Application["SignalRConnectionRecovery"];
if (signalRConnectionRecovery != null && signalRConnectionRecovery.IsAlive)
{
signalRConnectionRecovery.Abort();
}
}
catch
{
///
}
}
I found this nice article about how to use async worker: http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx
And this:
http://code.msdn.microsoft.com/CSASPNETBackgroundWorker-dda8d7b6
But I think for my needs this one will be perfect:
http://forums.asp.net/t/1433665.aspx/1
ASP.NET is not designed to handle this kind of requirement. If you need something to run constantly, you would be better off creating a windows service.
Update
ASP.NET is not designed for long running tasks. It's designed to respond quickly to HTTP requests. See Cyborgx37's answer or Can I use threads to carry out long-running jobs on IIS? for a few reasons why.
Update
Now that you finally mentioned you are working with SignalR, I see that you are trying to host SignalR within ASP.NET, correct? I think you're going about this the wrong way, see the example NuGet package referenced on the project wiki. This example uses an IAsyncHttpHandler to manage tasks.
You can start a thread in your global.asax, however it will only run till your asp.net process get recycled. This will happen at least once a day, or when no one uses of your site. If the process get recycled, the only way the thread is restarted agian, is when you have a hit on your site. So the thread is not running continueuosly.
To get a continues process it is better to start a windows service.
If you do the 'In process' solution, it realy depends on what your are doing. The Thread itself will not cause you any problems in memory or deadlocks. You should add a meganism to stop your thread when the application stops. Otherwise restarting will take a long time, because it will wait for your thread to stop.
This is an old post, but as I was seraching for this, I would like to report that in .NET 4.5.2 there is a native way to do it with QueueBackgroundWorkItem.
Take a look at this post: https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/
MarianoC
It depends what you are trying to accomplish in your while loop, but in general this is the kind of situation where a Windows Service is the best answer. Installing a Windows Service is going to require that you have admin privileges on the web server.
With an infinite loop you end up with a lot of issues regard the Windows message pump. This is the thing that keeps a Windows application alive even when the application isn't "doing" anything. Without it, a program simply ends.
The problem with an infinite loop is that the application is stuck "doing" something, which prevents other applications (or threads) from "doing" their thing. There have been a few workarounds, such as the DoEvents in Windows Forms, but they all have some serious drawbacks when it comes to responsiveness and resource management. (Acceptable on a small LOB application, maybe not on a web server.) Even if the while-loop is on a separate thread, it will use up all available processing power.
Asynchronus programming is really designed more for long-running processes, such as waiting for a database to return a result or waiting for a printer to come online. In these cases, it's the external process that is taking a long time, not a while-loop.
If a Window Service is not possible, then I think your best bet is going to be setting up a separate thread with its own message pump, but it's a bit complicated. I've never done it on a web server, but you might be able to start an Application. This will provide a message pump for you and allow you to respond to Windows events, etc. The only problem is that this is going to start a Windows application (either WPF or WinForms), which may not be desirable on a web server.
What are you trying to accomplish? Is there another way you might go about it?
I found this nice article about how to use async worker, will give it a try. http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx
And this:
http://code.msdn.microsoft.com/CSASPNETBackgroundWorker-dda8d7b6
But I think for my needs this one will be perfect:
http://forums.asp.net/t/1433665.aspx/1

Long-running thread process under ASP.NET + WCF

Duplicate
This is a close duplicate of Dealing with a longer running process in WCF. Please considering posting your answer to that one instead of this.
Original Question
I'm implementing the business layer of an application that must run some background processes at scheduled times. The business layer is made up of several WCF services all running under the same web application.
The idea is defining a set of 'tasks' that must be run at different times (eg. every 5 minutes, everyday at 23:00, etc). That wouldn't be hard to implement as a windows service, but the problem is, the tasks need access to data caches that are living in the services, so this 'scheduler' must run under the IIS context in order to access that data.
What I'm doing currently is using a custom ServiceHostFactory in one of the WCF services which spawns a child thread and returns. The child thread sleeps and wakes up every X minutes to see if there are scheduled tasks and executes them.
But I'm worried about IIS randomly killing my thread when it recycles the application pool or after some inactive time (eg. no activity on any of the WCF services, which listen for requests from the presentation layer). The thread must run uninterrupted regardless of activity on the services. Is this really possible?
I have found an article by someone doing the same thing, but his solution seems to be pinging the server from the child thread itself regularly. Hopefully there is a better solution.
I have at some point implemented a Windows Service that would load a web page on a regular basis. The purpose of that was was that the site was hosting a Workflow Foundation runtime, and we wanted to ensure that the web application was brought back up after IIS recycling the application pool. Perhaps the same approach can be used in this case; have a service (or Scheduled Task in Windows; even simpler) run every x minutes and load a page that will check for tasks.
Is it a possibility to run either a Windows Service or place applications in the Windows Scheduler to execute methods in the WCF at certain times? Maybe use a BackgroundWorker inside the WCF. Another option would be for WCF to spawn other applications to do the business logic, passing the appropriate data, or pointers to the data in memory(unsafe).

What should I be aware of when threading in ASP.NET?

Recently, the book on threading for Winforms application (Concurrent programming on Windows by Joe Duffy) was released. This book, focused on winforms, is 1000 pages.
What gotchas are there in ASP.NET threading? I'm sure there are plenty of gotchas to be aware of when implementing threading in ASP.NET. What should I be aware of?
Thanks
Since each http request received by IIS is processed separately, on it's own thread anyway, the only issues you should have is if you kick off some long running process from within the scope of a single http request. In that case, I would put such code into a separate referenced dependant assembly, coded like a middle-tier component, with no dependance or coupling to the ASP.Net model at all, and handle whatever concurrency issues arose within that assembly separately, without worrying about the ASP.Net model at all...
Jeff Richter over at Wintellect has a library called PowerThreading. It is very useful if you are developing applications on .NET. => Power Threading Library
Check for his presentations online at various events.
Usually you are encouraged to use the thread pool in .Net because it of the many benefits of having things managed on your behalf.....but NOT in ASP.net.
Since ASP.net is already multi-threaded, it uses the thread pool to serve requests that are mapped to the ASP.net ISAPI filter, and since the thread pool is fixed in size, by using it you are basically taking threads away that are set aside to do the job of handling request.
In small, low-traffic websites, this is not an issue, but in larger, high-traffic websites you end up competing for and consuming threads that the ASP.net process relies on.
If you want to use threading, it is fine to do something like....
Thread thread = new Thread(threadStarter);
thread.IsBackground = true;
thread.Start();
but with a warning: be sure that the IsBackground is set to true because if it isn't the thread exists in the foreground and will likely prevent the IIS worker process from recycling or restarting.
First, are you talking about asynchronous ASP.NET? Or using the ThreadPool/spinning up your own threads?
If you aren't talking about asynchronous ASP.NET, the main question to answer is: what work would you be doing in the other threads and would the work be specific to a request/response cycle, or is it more about processing global tasks in the background?
EDIT
If you need to handle concurrent operations (a better term than multi-threaded IMO) for a given request/response cycle, then use the asynchronous features of ASP.NET. These provide an abstraction over IIS's support for concurrency, allowing the server to process other requests while the current request is waiting for work to complete.
For background processing of global tasks, I would not use ASP.NET at all. You should assume that IIS will recycle your AppPool at a random point in time. You also should not assume that IIS will run your AppPool on any sort of schedule. Any important background processing should be done outside of IIS, either as a scheduled task or a Windows Service. The approach I usually take is to have a Windows Service and a shared work-queue where the web-site can post work items. The queue can be a database table, a reliable message-based queue (MSMQ, etc), files on the file system, etc.
The immediate thing that comes to mind is, why would you "implement threading" in ASP.NET.
You do need to be conscious all the time that ASP.NET is multi-threaded since many requests can be processed simulatenously each in its own thread. So for example use of static fields needs to take threading into account.
However its rare that you would want to spin up a new thread in code yourself.
As far as the usual winforms issues with threading in the UI is concerned these issues are not present in ASP.NET. There is no window based message pump to worry about.
It is possible to create asynchronous pages in ASP.NET. These will perform all steps up to a certain point. These steps will include asynchronously fetching data, for instance. When all the asynchronous tasks have completed, the remainder of the page lifecycle will execute. In the meantime, a worker thread was not tied up waiting for database I/O to complete.
In this model, all extra threads are executing while the request, and the page instance, and all the controls, still exist. You have to be careful when starting your own threads, that, by the time the thread executes, it's possible that the request, page instance, and controls will have been Disposed.
Also, as usual, be certain that multiple threads will actually improve performance. Often, additional threads will make things worse.
The gotchas are pretty much the same as in any multithreaded application.
The classes involved in processing a request (Page, Controls, HttpContext.Current, ...) are specific to that request so don't need any special handling.
Similarly for any classes you instantiate as local variables or fields within these classes, and for access to Session.
But, as usual, you need to synchronize access to shared resources such as:
Static (C#) / Shared(VB.NET) references.
Singletons
External resources such as the file system
... etc...
I've seen threading bugs too often in ASP.NET apps, e.g. a singleton being used by multiple concurrent requests without synchronization, resulting in user A seeing user B's data.

Resources