I have an ASP.Net application that needs needs to have some work performed by another machine. To do this I am leaving a message on queue visible to both machines. When the work is done a message is left on second queue.
I need the ASP.Net application to check the second queue periodically to see if any of the tasks are complete.
Where is the best place to but such a loop? Global.asax?
I remember reading somewhere that you can get a function called after an interval. Would that be suitable?
To achieve periodical tasks on asp.net, I've found two acceptable approaches:
Spawn a thread during Application_Start at global.asax, in a while loop (1) Do the work (2) Sleep the thread for an interval.
Again in Application_Start, insert a dummy item into asp.net cache, expires in a certain interval and give that cache item a callback to be called when it's expired. In that callback, you can do the work and insert the cache item back the same way.
In both ways, you need to make sure that your thread keeps working even if there happens an error. You may place a restore code in SessionStart and BeginRequest to check your thread or cache item is there, and renew it if something has happened to it.
I assume that this is done on a regular basis, and that some other process puts the items on the queue?
If that is the case, you might put something in Global.asax that on application start creates a separate thread that simply monitors the queue, you could use a timer to have that thread sleep for X seconds, then check for results.
Related
For logging purposes of an ASP.NET web application, I keep some state information in a static class. These fields are marked [ThreadStatic] so every thread has its own copy of the field. The logging methods are called from the HttpApplication event methods:
Application_BeginRequest (request start, initialise state)
Application_AcquireRequestState (session and user are known)
Application_EndRequest (request end, clean up)
I can now observe that, under certain circumstances, a page request is processed in different threads. The BeginRequest event runs on thread 18 while the following events run on thread 4. Of course my thread-static data is then not available and an error occurs.
Most of the time this works just fine and every request is processed in a single thread only. But when I request a page that loads ~5 seconds and after 1-2 seconds click on another link, both requests run in parallel. The first is completed on thread 24 (where it was also started) after 5 seconds, while the other starts on thread 18, but after the first request has completed, the second continues to run on thread 4.
Trying it with 3 overlapping long requests, it's a pure chaos. I can even watch two requests starting on the same thread while they later continue on different threads each. There doesn't seem to be any relationship between a request and a thread.
How can it be that a request is changing threads? It's losing all of its state if it decides to move on to another thread. And every description I can find says that it all happens in a single thread.
ASP.NET 4.0 on IIS 7, Windows Server 2008 R2, x64.
Alternative: If I cannot rely on requests being processed in only a single thread from the start to the end, then what would be the best location to store small amounts of per-request data (currently an integer and a class) that is very fast accessibly? And preferably also works without a reference to System.Web (my code is targeting the client profile as well). I know about HttpContext.Current.Items[key] but it's looked up somewhere deep in the remoting assembly and involves a dictionary which seems a lot slower than a thread-static field.
ASP.NET is thread agile and a request can be processed on more than one thread (but not more than one at time). Because of this you really can't use ThreadStatics in ASP.NET. However, you can safely use the HttpContext.Items dictionary to store things which need to be scoped to a single request.
To allow your code to work outside the context of an ASP.NET application, you could create a wrapper that swaps HttpContext / CallContext, depending on which environment the code is in. Here is an example of such a wrapper.
I am migrating an app written on asp.net 1.1. There is a process which can take 5 minutes on one page, processing data in SQL, and letting the user know when it's complete.
To get around the HTTP page timeout, the process runs asynchronously and the page refreshes every 5 seconds checking for completion. It's very simple. Here is the problem: I use a session variable as a semaphore to signal process completion.
This is not working now as I cannot read the semaphore set in the asynch process. The asynch process can read the session from the calling routine, but cannot write back.
First, is there a way to get the asynch process to write to a session variable which can be read by another process? This probably is not the best approach today, but getting the app working is my biggest priority.
Second, if I rewrite it, what approach should be used? This is an asp web app. Not MVC.
use callback technologie it allow you to query an operation server side from your client and get a return from server so no session to manage any more:
http://msdn.microsoft.com/en-us/library/ms178210(v=vs.80).aspx
I'd like to start using asynchronous processing in IIS. Edit: I'm talking about using the task parallel library.
For example, on certain page loads I want to log a bunch of crap, send an email, update some tables, etc. But I don't want to make the user wait for me to log all that crap.
So normally what I do is I have a static Queue that I push the log info onto, and then I have a cron job that calls a special page every 10 minutes whose OnLoad flushes out the queue. This works, but it's kind of clunky to setup, especially when you want to log 50 things. I'd rather do this:
Task.CreateNew(() => Log(theStuff));
However I'm terrified of running tasks in IIS because one slip up and your entire website goes down.
So now I have
SafeTask.FireAndForget(() => Log(theStuff));
This wraps the delegate in some try/catch and passes it into Task.CreateNew. So if someone changes something that affects something else that generates an exception somewhere else that accidentally gets thrown on the task thread, we get a notification instead of a crashed website. Also, the error notification inside the catch is also inside its own try/catch, and the catch for that also has a try/catch that tries to log in a different way.
Now that I can safely run stuff asynchronously in IIS, what other things do I need to worry about before I can start using my SafeTask class?
Every request in IIS and .net is processed in one thread by default. This thread comes from a thread pool called the "Application Pool". Existing threads are reused so you can't really use them for thread state unless you clear or set it every time. You define the size of this thread pool using a formula from MSDN in the machine.config or even your web.config.
Now, every async function call is put on a different thread. This includes async web service calls, async page functions, async delegates, etc. This thread comes from the "application pool" thus reducing the number of thread available for IIS to service new requests.
Most likely, your application will work just fine while using async function calls. In case you are worried or you have a lot of async tasks then you may want to create your own thread pool or look at SmartThreadPool on codeplex.
Hope this helps.
Consider using the page's OnUnload event. Read about it here: http://msdn.microsoft.com/en-us/library/ms178472.aspx
This event fires after the content is sent to the user (so the user isn't blocked while you do work), and should completely satisfy your requirement without introducing additional threads.
Specific to your question, you should be concerned about thread pool exhaustion only if your load and performance testing suggests you're running up against thread limits. If you're not then what you propose is certainly reasonable.
I'm not talking about asynchronous pages or asynchronous handlers, I just want to know if I should be afraid of any side effect when I invoke an asynchronous method that will end after the page is finished rendering.
Example given: Each time that a user do login, I have to launch a heavy and time consuming SQL operation, but the user doesn't need to know the result of that operation, so I can execute the query using BeginExecuteNonQuery without pass any callback, and finish rendering the page.
My concern is, what happen if the HTTP call ends (because the page is served) and whatever I've executed asynchronously is already running? is ASP.NET or IIS going to cut, destroy, void anything?
Cheers.
That operation will run, even when the request has finished. However, please note that the ASP.NET host aggressively kills threads. When IIS has any reason for unloading or recycling the AppDomain, your background thread will be killed. Unloading happens in several situations. For instance when no new requests have come in for a certain period of time. Or when too many exceptions are fired from the application within a certain period of time. Or when the memory pressure gets too high.
If you need the guarantee, that the operation will finish, I think there are three things you can do:
Speed up the operation so that it can run synchronously, or
Move that that heavy operation to a Windows Service and let that execute it, or
You can hook onto the HostingEnvironment.RegisterObject method (as Phill Haack explains here) (demands full trust) to prevent the AppDomain to go down while that thread is running.
If you have a callback registered, the process will comeback to notify the callback otherwise it will still complete the job. AFAIK - neither ASP.NET or IIS will cut/destroy or void anything as the execution was already ordered and it has to complete.
In an ASP.NET MVC application during application_start a new thread gets startet. The thread loads data into the Cache and takes 5 minutes. The application needs to be aware that the loading is in process. Thats why I want to set a flag in an application variable.
I set Application["LoadingCacheActive"] to true when I start the thread.
I dont find a way to set this variable to false when the thread finished. I dont want to use thread.Join, because the application_start has to complete imediately. Inside the created thread I cant set the the variable, because HttpContext.Current is not available.
Any suggestion?
You can use a static AutoResetEvent/ManualResetEvent data member in your Application class. Create the event as not set initially. When you app needs to check whether the thread is finished, it can call WaitOne(0) to test the state of the event. When the thread is finished, it can set the event. If you are using ManualResetEvent, you need to reset it before starting new thread.
You can also use Thread.ThreadState, however, as MSDN states:
Thread state is only of interest in
debugging scenarios. Your code should
never use thread state to synchronize
the activities of threads.
I've had to do similar things. The easiest way is to clear the flag in the last line in the thread.
EDIT: Franci Penov is right, your thread might get killed by a application pool shutdown. However in this case that should not harm you.