Calling method Asyncronously from aspx - asp.net

i am using .net4.0 framework
i am working on Web Project using c#
i want to make some request which will populate some items in cache beforehand.
Ex.
user comes to the home page of application.
[ i will write some code in Home Page(.ASPX) which will call some method which will read some files from disk and put them into cache though i don't need this cache on home page... at this point as reading files from disk is going to be somewhat lengthy operation... i would to load home page completely without waiting for response from method(which is going to read files from disk)]
Something like
function page_load{
CacheGenerator.CreateCache();//this is going to be heavy operation..i don't want to wait for this operation to complete
repose.write("Hello world:); // this statement should run moment after above function is called
}
and one more thing can we do this without using threading.

Anything asynchronous is "using threading" in one way or another.
More importantly, you should not start any async operation from a page. The page only exists in memory for the duration of the request. Your async operation may complete after the page no longer exists in memory.
You may be able to use the Task class to start an async operation from the Application_Start event in global.asax.

Related

Where to put initializing code in an ASP.Net MVC app?

I have a ASP.NET MVC4 web app, and I want some code to be executed the first time an app starts. The code basically loads a bunch of data from the database and stores it in a cache, so that any future requests can look up the data from the cache.
Where is the correct place to put this code? Should I simply add my line of code to Global.asax, or is there a best practice for calling code once an app starts?
Have a separate class to do the data initialization and call the respective method from Global.asax. The Global.asax should basically serve as an orchestrator. The individual initializations such as DI container initialization, cache initialization, route initialization etc. should sit in their own classes, thus honouring the single responsibility principle.
Global.asax.cs:Application_Start()
Same place you do things like register routes.
This is exactly where I initialize caches as well. I also check the cache expiration time on each Application_BeginRequest() to see if it needs to be updated.
You could place the code in Application_Start in Global.asax.
Or you could use the Lazy type on a static member, and it'll only initialize when it's first called (and it remains in memory for as long as the application runs). This has the advantage of not slowing application start up unnecessarily.
For instance, this example is for a compiled Regex, but could also be done with loading data:
public static Lazy<Regex> LibraryTagsRegex =
new Lazy<Regex>(() => new Regex(#"^library/tagged/(?<Tags>.+)", RegexOptions.Compiled));

.NET page caching but still receive query string

Is it possible to cache a page render on an iis web server, but still receive and write query string values (that don't affect output) to the database? So that the page render does not have to wait for the database trip to execute in order to serve the page? If possible, how do I implement?
For example, we track various affiliate and search marketing data via query strings, and in the master page code behind, we write the given query string data to the database. The output of the page doesn't change at all for the user (however we may set a cookie based off the qs parameter).
My understanding is that the page render has to wait for the database trip to fully execute in order to render the page. Is that even true?
Yes in general though it can depend on how one handles the caching.
First, you should move that tracking stuff to where it belongs -- a HttpModule. Page need not concern itself. Second, what you probably want to look into is some sort of fire and forget service call or message queueing. This makes the database write a non-blocking operation rather than a blocking operation.
Some options for making the operation non-blocking:
if you are actually writing to a web service, there is an underappreciated [OperationContract(IsOneWay = true)] decoration. Tells the generated proxy to fire and forget the call, will not wait for a response.
Another option would be to use the Asynchronous ADO.NET bits, especially BeginExecuteNonQuery. If you don't handle the callback this should just execute off your thread.
You could always just spawn a thread and deal with it in a non-blocking manner yourself. Just be real careful about handling errors on this thread -- unhandled exceptions will take out the app domain.

HTTPHandler : IRequiresSessionState halts execution of pages

I have ASHX HTTPHandler which implements IRequiresSessionState. When I call this handler, and call aspx page of same application in another window, aspx page does not start processing until ashx page finishes processing. Even call to same ashx page from two different windows show that page which gets called first executes and then the next one.
When I do not implement IRequiresSessionState, pages load asynchronously without waiting for other page to complete.
This could be serious bottleneck for end user, who would like to work in multiple windows.
Session have user specific data. If above approach does not work, need alternative way to store user specific data for session, which can be used in HTTPHandler.
Other Info:
- Am using ashx handler to process and send file which needs Session internally.
session state access requires that the aspx pages, and handler, run sequentially. Each page/handler may read from and write to the session state. To handle this without creating any errors in the session state .net will only run one at a time.
As Darin suggested, running with the read only session state will improve the situation. Asp.net will allow multiple handlers to run at the same time if they require only read access. However, the page will require write access to the session, so no handlers will run when the aspx page itself is running. This is the standard multi-reader single-writer locking pattern. You can have multiple readers at the same time, but only a single writer.
The only way to make this work is to have the handlers not require session state so that they run at the same time that t he aspx page is running.
You can work around this, by finding another way to store this data instead of using session state. You can implement your own shared cache/data structure, but you will need to provide similar locking (multi-reader/single writer) for that structure as well.
In addition to the points made by #Mike about IRequiresSessionState forcing each "user" (session) to only process one request at a time, there is good for another reason to want this.
Suppose you have an ajax service (implemented with a Generic Handler - *.ashx) which performs an "update" for a specific user based on the posted data. Let's say the update is heavy (around 250ms) and involves a "read/merge/write" process to the database (again data is isolated to an individual user). The client (app, website etc.) however can perform multiple calls in quick succession which the server has no control of.
By implementing IRequiresSessionState (simply including it as an inteface to your Generic Handler) ASP.NET will ensure that for a given user/session requests are handled serially. Multiple users however can still make calls to the update in parallel. This can allow us to avoid the "lost update problem" as the 2nd request won't retrieve a copy of the data until the 1st request has finished updating it.
public class SaveDataHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
// Read request parameters
// Read database (user specific data)
// Process
// Write back to database (user specific data)
}
public bool IsReusable => false;
}

Calling a method in an ASP.NET application from a Windows application

Other than using a web service, is there anyway to call a method in a web app from a windows application? Both run on the same machine.
I basically want to schedule a job to run a windows app which updates some file (for a bayesian spam filter), then I want to notify the web app to reload that file.
I know this can be done in other ways but I'm curious to know whether it's possible anyway.
You can make your windows app connect to the web app and do a GET in a page that responds by reloading your file, I don't think it is strictly necessary to use a web service. This way you can also make it happen from a web browser.
A Web Service is the "right" way if you want them to communicate directly. However, I've found it easier in some situations to coordinate via database records. For example, my web app has bulk email capability. To make it work, the web app just leaves a database record behind specifying the email to be sent. The WinApp scans periodically for these records and, when it finds one with an "unprocessed" status, it takes the appropriate action. This works like a charm for me in a very high volume environment.
You cannot quite do this in the other direction only because web apps don't generally sit around in a timing loop (there are ways around this but they aren't worth the effort). Thus, you'll require some type of initiating action to let the web app know when to reload the file. To do this, you could use the following code to do a GET on a page:
WebRequest wrContent = WebRequest.Create("http://www.yourUrl.com/yourpage.aspx");
Stream objStream = wrContent.GetResponse().GetResponseStream();
// I don't think you'll need the stream Reader but I include it for completeness
StreamReader objStreamReader = new StreamReader(objStream);
You'll then reload the file in the PageLoad method whenever this page is opened.
How is the web application loading the file? If you were using a dependency on the Cache object, then simply updating the file will invalidate the Cache entry, causing your code to reload that entry when it is found to be null (or based on the "invalidated" event).
Otherwise, I don't know how you would notify the application to update the file.
An ASP.NET application only exists as an instance to serve a request. This is why web services are an easy way to handle this - the application has been instantiated to serve the service request. If you could be sure the instance existed and got a handle to it, you could use remoting. But without having a concrete handle to an instance of the application, you can't invoke the method directly.
There's plenty of other ways to communicate. You could use a database or some other kind of list which both applications poll and update periodically. There are plenty of asynchronous MQ solutions out there.
So you'll create a page in your webapp specifically for this purpose. Use a Get request and pass in a url parameter. Then in the page_load event check for this paremter. if it exists then do your processing. By passing in the parameter you'll prevent accidental page loads that will cause the file to be uploaded and processed when you don't want it to be.
From the windows app make the url Get request by using the .Net HttpWebRequest. Example here: http://www.codeproject.com/KB/webservices/HttpWebRequest_Response.aspx

ASP.NET concurrency

I have an ASP.NET application that starts a long running operation during the Event Handler phase in the ASP.NET Page life cycle. This occurs when the end user pushes a button a bunch of queries are made to a database, a bunch of maps are generated, and then a movie is made from jpeg images of the maps. This process can take over a minute to complete.
Here's a link to the application
http://maxim.ucsd.edu/mapmaker/cbeo.aspx
I've tried using a thread from the threadpool, creating and launching my own thread and using AsyncCallback framework. The problem is that the new thread is run under a different userid. I assume the main thread is run under ASPNET, the new thread is run under AD\MAXIM$ where MAXIM is the hostname. I know this because there is an error when it tries to connect to the database.
Why is the new thread under a different userid?
If I can figure out the userid issue, what I'd like to do is check if the movie making process has finished by examining a Session variable in a Page_Load method, then add a link to the page to access the movie.
Does anyone have any good examples of using concurrency in a ASP.NET application that uses or creates threads in an EventHandler callback?
Thanks,
Matt
Did you read this?: http://msdn.microsoft.com/en-us/magazine/cc163725.aspx
Quoting one relevant portion from that link (you should read the whole thing):
A final point to keep in mind as you build asynchronous pages is that you should not launch asynchronous operations that borrow from the same thread pool that ASP.NET uses.
Not addressing the specific problem you asked about, but this is likely to come up soon:
At what point is this video used?
If it's displayed in the page or downloaded by the user, what does the generated html that the browser uses to get the video look like? The browser has to call that video somewhere using a separate http request, and you might do better by creating a separate http handler (*.ashx file) to handle that request, and just writing the url for that handler in your page.
If it's for storage or view elsewhere you should consider just saving the information needed to create the video at this point and deferring the actual work until the video is finally requested.
The problem is that the new thread is run under a different userid. I assume the main thread is run under ASPNET, the new thread is run under AD\MAXIM$ where MAXIM is the hostname.
ASPNET is a local account, when the request travels over a network it will use the computer's credentials (AD\MAXIM$).
What may be happening, is that you're running under impersonation in the request - and without in the ThreadPool. If that's the case, you might be able to store the current WindowsIdentity for the request, and then impersonate that identity in the ThreadPool.
Or, just let the ThreadPool hit the DB with Sql Authentication (username and password).

Resources